package de.ovgu.cide.editor; import java.util.LinkedList; import java.util.List; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import cide.gast.ASTVisitor; import cide.gast.ASTWrappers; import cide.gast.IASTNode; /** * searches to AST for nodes that lie in a specified selection range. returns * only the toplevel nodes (and their wrapped children) as far as possible * * this is used to determine which nodes should be colored for a user selection * * * @author ckaestne * */ public class SelectionFinder extends ASTVisitor { private final List<IASTNode> selectedNodes; private final List<IASTNode> knownNodes = new LinkedList<IASTNode>(); private final int offset; private final int length; private final boolean optionalOnly; /** * * @param selectedNodes * empty list which holds the result after the visitor is run * @param selection * @param optionalOnly */ public SelectionFinder(List<IASTNode> selectedNodes, ITextSelection selection, boolean optionalOnly) { this(selectedNodes, selection.getOffset(), selection.getLength(), optionalOnly); } public SelectionFinder(List<IASTNode> selectedNodes, IRegion region, boolean optionalOnly) { this(selectedNodes, region.getOffset(), region.getLength(), optionalOnly); } public SelectionFinder(List<IASTNode> selectedNodes, int offset, int length, boolean optionalOnly) { this.selectedNodes = selectedNodes; this.offset = offset; this.length = length; this.optionalOnly = optionalOnly; } @Override public boolean visit(IASTNode node) { boolean r = super.visit(node); if (node.getStartPosition() >= offset && (node.getStartPosition() + node.getLength()) <= (offset + length)) { if (!optionalOnly || node.isOptional()) { IASTNode parent = node.getParent(); boolean parentAlreadySelected = selectedNodes.contains(parent); boolean hasKnownParent = knownNodes.contains(parent); // Dieser Parameter wirkt sich nur aus, wenn auch // nicht-optionale Knoten selektiert werden k�nnen boolean parentRegionIsIdentical = !optionalOnly && (parent.getStartPosition() == node .getStartPosition()) && (parent.getLength() == node.getLength()); boolean inheritsColors = ASTWrappers.inheritsColors(parent, node); if (!hasKnownParent || parentRegionIsIdentical || (!inheritsColors && parentAlreadySelected)) { selectedNodes.add(node); if (parentRegionIsIdentical) selectedNodes.remove(parent); } } knownNodes.add(node); } return r; } public List<IASTNode> getAllSelectedNodes() { return knownNodes; } }