| /*=============================================================================# |
| # Copyright (c) 2008, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ltk.ui.util; |
| |
| import java.util.Iterator; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.ui.IWorkbenchPart; |
| |
| import org.eclipse.statet.jcommons.lang.NonNull; |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.text.core.BasicTextRegion; |
| import org.eclipse.statet.jcommons.text.core.TextRegion; |
| |
| import org.eclipse.statet.ecommons.text.core.JFaceTextRegion; |
| |
| import org.eclipse.statet.ltk.ast.core.AstInfo; |
| import org.eclipse.statet.ltk.ast.core.AstNode; |
| import org.eclipse.statet.ltk.ast.core.util.AstSelection; |
| import org.eclipse.statet.ltk.model.core.LtkModelUtils; |
| import org.eclipse.statet.ltk.model.core.ModelManager; |
| import org.eclipse.statet.ltk.model.core.element.LtkModelElement; |
| import org.eclipse.statet.ltk.model.core.element.SourceElement; |
| import org.eclipse.statet.ltk.model.core.element.SourceStructElement; |
| import org.eclipse.statet.ltk.model.core.element.SourceUnit; |
| import org.eclipse.statet.ltk.model.core.element.SourceUnitModelInfo; |
| import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor; |
| |
| |
| @NonNullByDefault |
| public class LTKSelectionUtils { |
| |
| |
| public static TextRegion toTextRegion(final ITextSelection selection) { |
| return JFaceTextRegion.newByStartLength(selection.getOffset(), selection.getLength()); |
| } |
| |
| public static TextRegion toTextRegion(final Point selectedRange) { |
| return JFaceTextRegion.newByStartLength(selectedRange.x, selectedRange.y); |
| } |
| |
| public static TextRegion toTextRegion(final IRegion region) { |
| return JFaceTextRegion.toTextRegion(region); |
| } |
| |
| public static TextRegion toTextRegion(final Position position) { |
| return JFaceTextRegion.newByStartLength(position.getOffset(), position.getLength()); |
| } |
| |
| |
| public static @Nullable TextRegion getRegionToSelect(final SourceElement<?> element) { |
| { final var region= element.getNameSourceRange(); |
| if (region != null) { |
| return region; |
| } |
| } |
| { final var region= element.getSourceRange(); |
| if (region != null) { |
| return new BasicTextRegion(region.getStartOffset()); |
| } |
| } |
| { final var region= element.getDocumentationRange(); |
| if (region != null) { |
| return new BasicTextRegion(region.getStartOffset()); |
| } |
| } |
| return null; |
| } |
| |
| |
| public static LtkModelElement @Nullable [] getSelectedElements(final @Nullable ISelection selection) { |
| if (selection instanceof IStructuredSelection) { |
| return getSelectedElements((IStructuredSelection) selection); |
| } |
| return null; |
| } |
| |
| public static LtkModelElement @Nullable [] getSelectedElements(final IStructuredSelection selection) { |
| final LtkModelElement[] elements= new @NonNull LtkModelElement[selection.size()]; |
| final Iterator<?> iter= selection.iterator(); |
| for (int i= 0; i < elements.length; i++) { |
| final Object next= iter.next(); |
| if (next instanceof LtkModelElement) { |
| elements[i]= (LtkModelElement) next; |
| } |
| else { |
| return null; |
| } |
| } |
| return elements; |
| } |
| |
| public static @Nullable SourceUnit getSingleSourceUnit(final IWorkbenchPart part) { |
| final SourceEditor editor= part.getAdapter(SourceEditor.class); |
| if (editor == null) { |
| return null; |
| } |
| return editor.getSourceUnit(); |
| } |
| |
| public static @Nullable AstNode getSelectedAstNode(final SourceUnit su, final String type, |
| final @Nullable ISelection selection, final IProgressMonitor monitor) { |
| if (selection instanceof ITextSelection) { |
| final ITextSelection textSelection= (ITextSelection) selection; |
| final SourceUnitModelInfo modelInfo= su.getModelInfo(type, ModelManager.MODEL_FILE, monitor); |
| if (modelInfo == null) { |
| return null; |
| } |
| final AstInfo info= modelInfo.getAst(); |
| if (info == null || info.getRoot() == null) { |
| return null; |
| } |
| final AstSelection astSelection= AstSelection.search(info.getRoot(), |
| textSelection.getOffset(), textSelection.getOffset()+textSelection.getLength(), |
| AstSelection.MODE_COVERING_SAME_LAST ); |
| return astSelection.getCovering(); |
| } |
| return null; |
| } |
| |
| public static @NonNull SourceStructElement @Nullable [] getSelectedSourceStructElements( |
| final @Nullable ISelection selection) { |
| if (selection instanceof IStructuredSelection) { |
| return getSelectedSourceStructElements((IStructuredSelection) selection); |
| } |
| return null; |
| } |
| |
| public static @NonNull SourceStructElement @Nullable [] getSelectedSourceStructElements( |
| final IStructuredSelection selection) { |
| final @NonNull SourceStructElement[] elements= new @NonNull SourceStructElement[selection.size()]; |
| final Iterator<?> iter= selection.iterator(); |
| for (int i= 0; i < elements.length; i++) { |
| final Object next= iter.next(); |
| if (next instanceof SourceStructElement) { |
| elements[i]= (SourceStructElement) next; |
| continue; |
| } |
| return null; |
| } |
| return elements; |
| } |
| |
| public static @NonNull IFile @Nullable [] getSelectedFiles(final @Nullable ISelection selection) { |
| if (selection instanceof IStructuredSelection) { |
| return getSelectedFiles((IStructuredSelection) selection); |
| } |
| return null; |
| } |
| |
| public static IFile @Nullable [] getSelectedFiles(final IStructuredSelection selection) { |
| final IFile[] elements= new @NonNull IFile[selection.size()]; |
| final Iterator<?> iter= selection.iterator(); |
| for (int i= 0; i < elements.length; i++) { |
| final Object next= iter.next(); |
| if (next instanceof IFile) { |
| elements[i]= (IFile) next; |
| continue; |
| } |
| if (next instanceof IAdaptable) { |
| elements[i]= ((IAdaptable) next).getAdapter(IFile.class); |
| if (elements[i] != null) { |
| continue; |
| } |
| } |
| return null; |
| } |
| return elements; |
| } |
| |
| public static SourceStructElement @Nullable [] getSelectedSourceStructElement( |
| final @Nullable SourceUnitModelInfo suModel, final ITextSelection selection) { |
| if (suModel != null) { |
| final SourceStructElement root= suModel.getSourceElement(); |
| final int selectionStart= selection.getOffset(); |
| final int selectionEnd= selectionStart + selection.getLength(); |
| if (selectionStart >= root.getSourceRange().getStartOffset() |
| && selectionEnd <= root.getSourceRange().getEndOffset()) { |
| return new SourceStructElement[] { |
| LtkModelUtils.getCoveringSourceElement(root, selectionStart, selectionEnd), |
| }; |
| } |
| } |
| return null; |
| } |
| |
| } |