| /*=============================================================================# |
| # Copyright (c) 2009, 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.r.ui.sourceediting; |
| |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITypedRegion; |
| import org.eclipse.jface.text.TextUtilities; |
| import org.eclipse.ui.PartInitException; |
| |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| 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.element.SourceElement; |
| import org.eclipse.statet.ltk.model.core.element.SourceUnit; |
| import org.eclipse.statet.ltk.ui.sourceediting.ISourceEditor; |
| import org.eclipse.statet.ltk.ui.sourceediting.actions.AbstractOpenDeclarationHandler; |
| import org.eclipse.statet.r.core.model.RElementAccess; |
| import org.eclipse.statet.r.core.model.RModel; |
| import org.eclipse.statet.r.core.model.RModelManager; |
| import org.eclipse.statet.r.core.model.RSourceUnit; |
| import org.eclipse.statet.r.core.model.RSourceUnitModelInfo; |
| import org.eclipse.statet.r.core.rlang.RTokens; |
| import org.eclipse.statet.r.core.rsource.ast.NodeType; |
| import org.eclipse.statet.r.core.rsource.ast.RAstNode; |
| import org.eclipse.statet.r.core.source.RDocumentConstants; |
| import org.eclipse.statet.r.core.source.RHeuristicTokenScanner; |
| |
| |
| public class ROpenDeclarationHandler extends AbstractOpenDeclarationHandler { |
| |
| |
| public static @Nullable RElementAccess searchAccess(final ISourceEditor editor, final IRegion region) { |
| // not for sub elements |
| try { |
| final IDocument document= editor.getViewer().getDocument(); |
| final RHeuristicTokenScanner scanner= RHeuristicTokenScanner.create( |
| editor.getDocumentContentInfo() ); |
| if (scanner == null) { |
| return null; |
| } |
| final ITypedRegion partition= TextUtilities.getPartition(document, |
| scanner.getDocumentPartitioning(), region.getOffset(), false ); |
| final SourceUnit su= editor.getSourceUnit(); |
| if (su instanceof RSourceUnit |
| && region.getOffset() < document.getLength() |
| && ( (RDocumentConstants.R_DEFAULT_CONTENT_CONSTRAINT.matches(partition.getType()) |
| && !RTokens.isRobustSeparator(document.getChar(region.getOffset()), false) ) |
| || partition.getType() == RDocumentConstants.R_QUOTED_SYMBOL_CONTENT_TYPE |
| || partition.getType() == RDocumentConstants.R_STRING_CONTENT_TYPE )) { |
| |
| final RSourceUnitModelInfo modelInfo= (RSourceUnitModelInfo)su.getModelInfo(RModel.R_TYPE_ID, |
| RModelManager.MODEL_FILE, new NullProgressMonitor() ); |
| if (modelInfo != null) { |
| final AstInfo astInfo= modelInfo.getAst(); |
| final AstSelection astSelection= AstSelection.search(astInfo.getRoot(), |
| region.getOffset(), region.getOffset() + region.getLength(), |
| AstSelection.MODE_COVERING_SAME_LAST ); |
| final AstNode covering= astSelection.getCovering(); |
| if (covering instanceof RAstNode) { |
| final RAstNode node= (RAstNode) covering; |
| if (node.getNodeType() == NodeType.SYMBOL || node.getNodeType() == NodeType.STRING_CONST) { |
| RAstNode current= node; |
| do { |
| final List<Object> attachments= current.getAttachments(); |
| for (final Object attachment : attachments) { |
| if (attachment instanceof RElementAccess) { |
| final RElementAccess access= (RElementAccess) attachment; |
| if (access.getNameNode() == node) { |
| return access; |
| } |
| } |
| } |
| current= current.getRParent(); |
| } while (current != null); |
| } |
| } |
| } |
| } |
| } |
| catch (final BadLocationException e) { |
| } |
| return null; |
| } |
| |
| |
| public ROpenDeclarationHandler() { |
| } |
| |
| |
| @Override |
| public boolean execute(final ISourceEditor editor, final IRegion selection) { |
| final RElementAccess access= searchAccess(editor, selection); |
| if (access != null) { |
| try { |
| final List<SourceElement> list= RModel.searchDeclaration(access, (RSourceUnit)editor.getSourceUnit()); |
| final ROpenDeclaration open= new ROpenDeclaration(); |
| final SourceElement element= open.selectElement(list, editor.getWorkbenchPart()); |
| if (element != null) { |
| open.open(element, true); |
| return true; |
| } |
| } |
| catch (final PartInitException e) { |
| logError(e, access.getDisplayName()); |
| } |
| catch (final CoreException e) { |
| return true; // cancelled |
| } |
| } |
| return false; |
| } |
| |
| } |