blob: 851f2089ce1811ee7f88f5ed4f93527c87bb3642 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2008, 2019 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.editors;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPartitioningException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.swt.graphics.Point;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.ecommons.text.ui.presentation.ITextPresentationConstants;
import org.eclipse.statet.ltk.ast.core.util.AstSelection;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnitModelInfo;
import org.eclipse.statet.ltk.ui.sourceediting.AbstractMarkOccurrencesProvider.RunData;
import org.eclipse.statet.r.core.model.IRModelInfo;
import org.eclipse.statet.r.core.model.RElementAccess;
import org.eclipse.statet.r.core.rsource.ast.DocuComment;
import org.eclipse.statet.r.core.rsource.ast.DocuTag;
import org.eclipse.statet.r.core.rsource.ast.NodeType;
import org.eclipse.statet.r.core.rsource.ast.RAst;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;
import org.eclipse.statet.r.core.rsource.ast.SourceComponent;
public class RMarkOccurrencesLocator {
public void run(final RunData run, final ISourceUnitModelInfo info,
final AstSelection astSelection, final ITextSelection orgSelection)
throws BadLocationException, BadPartitioningException, UnsupportedOperationException {
RAstNode node = (RAstNode) astSelection.getCovering();
if (checkForAccess(run, node)) {
return;
}
if (orgSelection != null && info instanceof IRModelInfo) {
final int start = orgSelection.getOffset();
final int stop = start + orgSelection.getLength();
if (info.getAst().getRoot() instanceof SourceComponent) {
final List<RAstNode> comments = ((SourceComponent) info.getAst().getRoot()).getComments();
for (final RAstNode comment : comments) {
if (comment.getEndOffset() < start) {
continue;
}
if (comment.getStartOffset() > stop) {
break;
}
if (comment.getNodeType() == NodeType.DOCU_AGGREGATION) {
final DocuComment docuComment = (DocuComment) comment;
final List<DocuTag> tags = docuComment.getTags();
for (final DocuTag tag : tags) {
if (tag.getEndOffset() < start) {
continue;
}
if (tag.getStartOffset() > stop) {
break;
}
final AstSelection selection = AstSelection.search(tag, start, stop, AstSelection.MODE_COVERING_SAME_LAST);
node = (RAstNode) selection.getCovering();
if (checkForAccess(run, node)) {
return;
}
}
}
}
}
}
}
private boolean checkForAccess(final RunData run, RAstNode node) throws BadLocationException {
if (node == null
|| !(node.getNodeType() == NodeType.SYMBOL || node.getNodeType() == NodeType.STRING_CONST)) {
return false;
}
do {
final List<Object> attachments= node.getAttachments();
for (final Object attachment : attachments) {
if (attachment instanceof RElementAccess) {
final RElementAccess access= (RElementAccess) attachment;
final Map<Annotation, Position> annotations = checkDefault(run, access);
if (annotations != null) {
run.set(annotations);
return true;
}
}
}
node = node.getRParent();
} while (node != null);
return false;
}
private Map<Annotation, Position> checkDefault(final RunData run, RElementAccess access) throws BadLocationException {
while (access != null) {
final RAstNode nameNode = access.getNameNode();
if (nameNode == null) {
return null;
}
if (run.accept(new Point(nameNode.getStartOffset(), nameNode.getEndOffset()))) {
final ImList<? extends RElementAccess> allAccess= access.getAllInUnit(false);
final Map<Annotation, Position> annotations= new LinkedHashMap<>(allAccess.size());
for (final RElementAccess aAccess : allAccess) {
final String message= run.doc.get(aAccess.getNode().getStartOffset(), aAccess.getNode().getLength());
annotations.put(
new Annotation((aAccess.isWriteAccess()) ?
ITextPresentationConstants.ANNOTATIONS_WRITE_OCCURRENCES_TYPE:
ITextPresentationConstants.ANNOTATIONS_COMMON_OCCURRENCES_TYPE,
false, message),
RAst.getElementNamePosition(aAccess.getNameNode()) );
}
return annotations;
}
access = access.getNextSegment();
}
return null;
}
}