| /*=============================================================================# |
| # Copyright (c) 2008, 2020 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.element.SourceUnitModelInfo; |
| import org.eclipse.statet.ltk.ui.sourceediting.AbstractMarkOccurrencesProvider.RunData; |
| import org.eclipse.statet.r.core.model.RElementAccess; |
| import org.eclipse.statet.r.core.model.RSourceUnitModelInfo; |
| 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.RAsts; |
| 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 SourceUnitModelInfo 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 RSourceUnitModelInfo) { |
| 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), |
| RAsts.getElementNamePosition(aAccess.getNameNode()) ); |
| } |
| return annotations; |
| } |
| access = access.getNextSegment(); |
| } |
| return null; |
| } |
| |
| } |