blob: d288f7fde66ee18881987868e45ba2e88ae7c66c [file] [log] [blame]
/*=============================================================================#
# 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;
}
}