ada.editor/src/org/netbeans/modules/ada/editor/navigator/AdaOccurrencesFinder.java
Add JVM compiler support.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2008 Sun Microsystems, Inc.
39 package org.netbeans.modules.ada.editor.navigator;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.LinkedList;
45 import java.util.List;
47 import java.util.logging.Level;
48 import java.util.logging.Logger;
49 import org.netbeans.modules.parsing.spi.Scheduler;
50 import org.netbeans.modules.parsing.spi.SchedulerEvent;
51 import org.netbeans.modules.ada.editor.CodeUtils;
52 import org.netbeans.modules.ada.editor.ast.ASTNode;
53 import org.netbeans.modules.ada.editor.ast.ASTUtils;
54 import org.netbeans.modules.ada.editor.ast.nodes.FormalParameter;
55 import org.netbeans.modules.ada.editor.ast.nodes.Identifier;
56 import org.netbeans.modules.ada.editor.ast.nodes.MethodDeclaration;
57 import org.netbeans.modules.ada.editor.ast.nodes.PackageBody;
58 import org.netbeans.modules.ada.editor.ast.nodes.PackageSpecification;
59 import org.netbeans.modules.ada.editor.ast.nodes.Scalar;
60 import org.netbeans.modules.ada.editor.ast.nodes.SingleFieldDeclaration;
61 import org.netbeans.modules.ada.editor.ast.nodes.SubprogramBody;
62 import org.netbeans.modules.ada.editor.ast.nodes.SubprogramSpecification;
63 import org.netbeans.modules.ada.editor.ast.nodes.TypeDeclaration;
64 import org.netbeans.modules.ada.editor.ast.nodes.TypeName;
65 import org.netbeans.modules.ada.editor.ast.nodes.Variable;
66 import org.netbeans.modules.ada.editor.ast.nodes.visitors.DefaultVisitor;
67 import org.netbeans.modules.ada.editor.navigator.SemiAttribute.AttributedElement;
68 import org.netbeans.modules.ada.editor.navigator.SemiAttribute.AttributedElement.Kind;
69 import org.netbeans.modules.csl.api.ColoringAttributes;
70 import org.netbeans.modules.csl.api.OccurrencesFinder;
71 import org.netbeans.modules.csl.api.OffsetRange;
72 import org.netbeans.modules.csl.spi.GsfUtilities;
73 import org.netbeans.modules.csl.spi.ParserResult;
74 import org.netbeans.modules.parsing.spi.Parser.Result;
77 * Based on org.netbeans.modules.php.editor.nav.OccurrencesFinderImpl
79 * @author Andrea Lucarelli
81 public class AdaOccurrencesFinder extends OccurrencesFinder {
83 private static final Logger LOGGER = Logger.getLogger(AdaOccurrencesFinder.class.getName());
85 private Map<OffsetRange, ColoringAttributes> range2Attribs;
87 public void setCaretPosition(int position) {
88 this.offset = position;
89 this.range2Attribs = new HashMap<OffsetRange, ColoringAttributes>();
92 public Map<OffsetRange, ColoringAttributes> getOccurrences() {
96 public void cancel() {
99 public void run(Result result, SchedulerEvent event) {
100 for (OffsetRange r : compute((ParserResult) result, GsfUtilities.getLastKnownCaretOffset(result.getSnapshot(), event))) {
101 range2Attribs.put(r, ColoringAttributes.MARK_OCCURRENCES);
105 static Collection<OffsetRange> compute(final ParserResult parameter, final int offset) {
106 final List<OffsetRange> result = new LinkedList<OffsetRange>();
107 final List<ASTNode> path = NavUtils.underCaret(parameter, offset);
108 final SemiAttribute attribute = SemiAttribute.semiAttribute(parameter);
109 final AttributedElement element = NavUtils.findElement(parameter, path, offset, attribute);
111 if (element == null) {
114 Identifier id = null;
115 Collections.reverse(path);
116 for (ASTNode astNode : path) {
117 if (astNode instanceof Identifier) {
118 Identifier identifier = (Identifier) astNode;
119 if (identifier != null) {
125 final Identifier identifier = id;
126 final List<ASTNode> usages = new LinkedList<ASTNode>();
127 final List<ASTNode> memberDeclaration = new LinkedList<ASTNode>();
129 LOGGER.setLevel(Level.FINE);
131 new DefaultVisitor() {
133 private String pkgName = null;
136 public void visit(MethodDeclaration node) {
137 boolean found = false;
138 if (element instanceof SemiAttribute.PackageMemberElement) {
139 SemiAttribute.PackageMemberElement pkgEl = (SemiAttribute.PackageMemberElement) element;
140 String methName = CodeUtils.extractMethodName(node);
141 Identifier methNode = node.getSubrogramName();
143 if (pkgName != null && pkgEl.getPackageName().equals(pkgName) && pkgEl.getName().equals(methName)) {
144 memberDeclaration.add(methNode);
145 usages.add(methNode);
146 if (node.getMethodName() != null) {
147 usages.add(node.getSubrogramNameEnd());
158 public void visit(TypeDeclaration node) {
159 boolean found = false;
160 if (element instanceof SemiAttribute.PackageMemberElement) {
161 SemiAttribute.PackageMemberElement pkgEl = (SemiAttribute.PackageMemberElement) element;
162 Identifier type = node.getTypeName();
163 String typeName = type.getName();
164 if (pkgName != null && pkgEl.getPackageName().equals(pkgName) && pkgEl.getName().equals(typeName)) {
165 memberDeclaration.add(type);
176 public void visit(SingleFieldDeclaration node) {
177 boolean found = false;
178 if (element instanceof SemiAttribute.PackageMemberElement) {
179 SemiAttribute.PackageMemberElement pkgEl = (SemiAttribute.PackageMemberElement) element;
180 Variable variable = node.getName();
181 String varName = CodeUtils.extractVariableName(variable);
182 if (pkgName != null && pkgEl.getPackageName().equals(pkgName) && pkgEl.getName().equals(varName)) {
183 memberDeclaration.add(variable);
184 usages.add(variable);
194 public void visit(SubprogramSpecification node) {
195 if (!(element instanceof SemiAttribute.PackageMemberElement)) {
196 if (element == attribute.getElement(node)) {
197 usages.add(node.getSubprogramName());
204 public void visit(SubprogramBody node) {
205 if (!(element instanceof SemiAttribute.PackageMemberElement)) {
206 if (element == attribute.getElement(node)) {
207 usages.add(node.getSubprogramSpecification().getSubprogramName());
208 if (node.getSubprogramNameEnd().getName() != null) {
209 usages.add(node.getSubprogramNameEnd());
217 public void visit(PackageSpecification node) {
218 if (element == attribute.getElement(node)) {
219 usages.add(node.getName());
220 if (node.getNameEnd().getName() != null) {
221 usages.add(node.getNameEnd());
224 pkgName = CodeUtils.extractPackageName(node);
227 * do not mark two method decl., if happens then remove
228 * the superclass method.
230 while (memberDeclaration.size() > 1) {
231 usages.remove(memberDeclaration.remove(0));
236 public void visit(PackageBody node) {
237 if (element == attribute.getElement(node)) {
238 usages.add(node.getName());
239 if (node.getNameEnd().getName() != null) {
240 usages.add(node.getNameEnd());
243 pkgName = CodeUtils.extractPackageName(node);
246 * do not mark two method decl., if happens then remove
247 * the superclass method.
249 while (memberDeclaration.size() > 1) {
250 usages.remove(memberDeclaration.remove(0));
255 public void visit(FormalParameter node) {
256 Variable parameterName = node.getParameterName();
257 if (parameterName != null) {
258 String name = parameterName.getName().getName();
259 if (name != null && element == attribute.getElement(parameterName)) {
260 usages.add(parameterName);
263 TypeName parameterType = CodeUtils.extractType(node.getParameterType());
264 if (parameterType != null) {
265 String name = parameterType.getTypeName().getName();
266 if (name != null && element == attribute.getElement(parameterType)) {
267 usages.add(parameterType);
274 public void visit(Variable node) {
275 if (element == attribute.getElement(node)) {
282 public void visit(TypeName node) {
283 if (element == attribute.getElement(node)) {
290 public void visit(Scalar scalar) {
291 if (element == attribute.getElement(scalar)) {
296 }.scan(ASTUtils.getRoot(parameter));
299 for (ASTNode n : usages) {
300 OffsetRange forNode = forNode(n, element.getKind());
301 if (n instanceof Identifier) {
302 LOGGER.fine("result " + occur + ": " + ((Identifier)n).getName());
303 LOGGER.fine("result " + occur + ": " + forNode);
306 if (forNode != null) {
314 private static OffsetRange forNode(ASTNode n, Kind kind) {
315 OffsetRange retval = null;
316 if (n instanceof Scalar && ((Scalar) n).getScalarType() == Scalar.Type.STRING && NavUtils.isQuoted(((Scalar) n).getStringValue())) {
317 retval = new OffsetRange(n.getStartOffset(), n.getEndOffset());
318 } else if (n instanceof Variable) {
319 retval = new OffsetRange(n.getStartOffset(), n.getEndOffset());
320 } else if (n != null) {
321 retval = new OffsetRange(n.getStartOffset(), n.getEndOffset());
327 public int getPriority() {
332 public Class<? extends Scheduler> getSchedulerClass() {
333 return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;