KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > editor > semantic > SemanticHighlighter


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.editor.semantic;
20
21 import com.sun.source.tree.AnnotationTree;
22 import com.sun.source.tree.ArrayAccessTree;
23 import com.sun.source.tree.ArrayTypeTree;
24 import com.sun.source.tree.AssertTree;
25 import com.sun.source.tree.AssignmentTree;
26 import com.sun.source.tree.BinaryTree;
27 import com.sun.source.tree.CaseTree;
28 import com.sun.source.tree.CatchTree;
29 import com.sun.source.tree.ClassTree;
30 import com.sun.source.tree.CompilationUnitTree;
31 import com.sun.source.tree.CompoundAssignmentTree;
32 import com.sun.source.tree.ConditionalExpressionTree;
33 import com.sun.source.tree.EnhancedForLoopTree;
34 import com.sun.source.tree.ExpressionStatementTree;
35 import com.sun.source.tree.ExpressionTree;
36 import com.sun.source.tree.IdentifierTree;
37 import com.sun.source.tree.ImportTree;
38 import com.sun.source.tree.InstanceOfTree;
39 import com.sun.source.tree.MemberSelectTree;
40 import com.sun.source.tree.MethodInvocationTree;
41 import com.sun.source.tree.MethodTree;
42 import com.sun.source.tree.NewArrayTree;
43 import com.sun.source.tree.NewClassTree;
44 import com.sun.source.tree.ParameterizedTypeTree;
45 import com.sun.source.tree.ParenthesizedTree;
46 import com.sun.source.tree.ReturnTree;
47 import com.sun.source.tree.ThrowTree;
48 import com.sun.source.tree.Tree;
49 import com.sun.source.tree.Tree.Kind;
50 import com.sun.source.tree.TypeCastTree;
51 import com.sun.source.tree.TypeParameterTree;
52 import com.sun.source.tree.UnaryTree;
53 import com.sun.source.tree.VariableTree;
54 import com.sun.source.util.SourcePositions;
55 import com.sun.source.util.TreePath;
56 import com.sun.source.util.TreePathScanner;
57 import java.awt.Color JavaDoc;
58 import java.beans.PropertyChangeListener JavaDoc;
59 import java.io.IOException JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.Arrays JavaDoc;
62 import java.util.Collection JavaDoc;
63 import java.util.Collections JavaDoc;
64 import java.util.EnumSet JavaDoc;
65 import java.util.HashMap JavaDoc;
66 import java.util.HashSet JavaDoc;
67 import java.util.List JavaDoc;
68 import java.util.Map JavaDoc;
69 import java.util.Set JavaDoc;
70 import java.util.logging.Level JavaDoc;
71 import java.util.logging.Logger JavaDoc;
72 import javax.lang.model.element.Element;
73 import javax.lang.model.element.ElementKind;
74 import javax.lang.model.element.ExecutableElement;
75 import javax.lang.model.element.Modifier;
76 import javax.lang.model.type.TypeKind;
77 import javax.swing.text.BadLocationException JavaDoc;
78 import javax.swing.text.Document JavaDoc;
79 import javax.swing.text.Position JavaDoc;
80 import javax.swing.text.StyledDocument JavaDoc;
81 import org.netbeans.api.java.source.CancellableTask;
82 import org.netbeans.api.java.source.CompilationInfo;
83 import org.netbeans.api.java.source.TreePathHandle;
84 import org.netbeans.api.java.source.support.CancellableTreePathScanner;
85 import org.netbeans.api.timers.TimesCollector;
86 import org.netbeans.editor.BaseDocument;
87 import org.netbeans.modules.editor.highlights.spi.Highlight;
88 import org.netbeans.modules.editor.highlights.spi.Highlighter;
89 import org.netbeans.spi.editor.hints.ChangeInfo;
90 import org.netbeans.spi.editor.hints.ErrorDescription;
91 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
92 import org.netbeans.spi.editor.hints.Fix;
93 import org.netbeans.spi.editor.hints.HintsController;
94 import org.netbeans.spi.editor.hints.LazyFixList;
95 import org.netbeans.spi.editor.hints.Severity;
96 import org.openide.ErrorManager;
97 import org.openide.cookies.EditorCookie;
98 import org.openide.filesystems.FileObject;
99 import org.openide.filesystems.FileUtil;
100 import org.openide.loaders.DataObject;
101 import org.openide.text.NbDocument;
102
103
104 /**
105  *
106  * @author Jan Lahoda
107  */

108 public class SemanticHighlighter extends ScanningCancellableTask<CompilationInfo> {
109     
110     private FileObject file;
111     
112     /** Creates a new instance of SemanticHighlighter */
113     SemanticHighlighter(FileObject file) {
114         this.file = file;
115     }
116
117     public Document JavaDoc getDocument() {
118         try {
119             DataObject d = DataObject.find(file);
120             EditorCookie ec = (EditorCookie) d.getCookie(EditorCookie.class);
121             
122             if (ec == null)
123                 return null;
124             
125             return ec.getDocument();
126         } catch (IOException JavaDoc e) {
127             Logger.getLogger(SemanticHighlighter.class.getName()).log(Level.INFO, "SemanticHighlighter: Cannot find DataObject for file: " + FileUtil.getFileDisplayName(file), e);
128             return null;
129         }
130     }
131     
132     public @Override JavaDoc void run(CompilationInfo info) {
133         resume();
134         
135         Document JavaDoc doc = getDocument();
136
137         if (doc == null) {
138             Logger.getLogger(SemanticHighlighter.class.getName()).log(Level.INFO, "SemanticHighlighter: Cannot get document!");
139             return ;
140         }
141
142         Set JavaDoc<Highlight> highlights = process(info, doc);
143         
144         if (isCancelled())
145             return;
146         
147         Highlighter.getDefault().setHighlights(file, "semantic", highlights);
148         OccurrencesMarkProvider.get(doc).setSematic(highlights);
149     }
150     
151     private void removeImport(Document JavaDoc doc, int start, int end) {
152         try {
153             int len = doc.getLength();
154             
155             while (start > 0 && "\t ".indexOf(doc.getText(start - 1, 1).charAt(0)) != (-1))
156                 start--;
157             
158             boolean wasNewLine = start == 0 || "\n".equals(doc.getText(start - 1, 1));
159             
160             while (end < len && "\t ".indexOf(doc.getText(end, 1).charAt(0)) != (-1))
161                 end++;
162             
163             if (wasNewLine && "\n".equals(doc.getText(end, 1)))
164                 end++;
165             
166             doc.remove(start, end - start);
167         } catch (BadLocationException JavaDoc e) {
168             ErrorManager.getDefault().notify(e);
169         }
170     }
171     
172     private static class FixAllImportsFixList implements LazyFixList {
173         private Fix removeImport;
174         private Fix removeAllUnusedImports;
175         private List JavaDoc<TreePathHandle> allUnusedImports;
176         
177         public FixAllImportsFixList(Fix removeImport, Fix removeAllUnusedImports, List JavaDoc<TreePathHandle> allUnusedImports) {
178             this.removeImport = removeImport;
179             this.removeAllUnusedImports = removeAllUnusedImports;
180             this.allUnusedImports = allUnusedImports;
181         }
182         
183         public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
184         }
185         
186         public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
187         }
188         
189         public boolean probablyContainsFixes() {
190             return true;
191         }
192         
193         private List JavaDoc<Fix> fixes;
194         
195         public synchronized List JavaDoc<Fix> getFixes() {
196             if (fixes != null)
197                 return fixes;
198             
199             if (allUnusedImports.size() > 1) {
200                 fixes = Arrays.asList(removeImport, removeAllUnusedImports);
201             } else {
202                 fixes = Collections.singletonList(removeImport);
203             }
204             
205             return fixes;
206         }
207         
208         public boolean isComputed() {
209             return true;
210         }
211     }
212     
213     Set JavaDoc<Highlight> process(CompilationInfo info, final Document JavaDoc doc) {
214         DetectorVisitor v = new DetectorVisitor(info, doc);
215         
216         long start = System.currentTimeMillis();
217         
218         Set JavaDoc<Highlight> result = new HashSet JavaDoc();
219         List JavaDoc<ErrorDescription> errors = new ArrayList JavaDoc<ErrorDescription>();
220
221         CompilationUnitTree cu = info.getCompilationUnit();
222         
223         scan(v, cu, null);
224         
225         if (isCancelled())
226             return Collections.emptySet();
227         
228         final List JavaDoc<TreePathHandle> allUnusedImports = new ArrayList JavaDoc<TreePathHandle>();
229         final Fix removeAllUnusedImports = RemoveUnusedImportFix.create(file, allUnusedImports);
230         
231         for (Element el : v.type2Highlight.keySet()) {
232             if (isCancelled())
233                 return Collections.emptySet();
234
235             final TreePath tree = v.type2Highlight.get(el);
236             
237             if (el == null || el.getSimpleName() == null)
238                 continue;
239             
240             Highlight h = Utilities.createHighlight(cu, info.getTrees().getSourcePositions(), doc, tree, EnumSet.of(ColoringAttributes.UNUSED), Color.GRAY);
241             
242             if (h != null) {
243                 result.add(h);
244             }
245             
246             final long startPos = info.getTrees().getSourcePositions().getStartPosition(cu, tree.getLeaf());
247             int line = (int) info.getCompilationUnit().getLineMap().getLineNumber(startPos);
248             
249             TreePathHandle handle = TreePathHandle.create(tree, info);
250             
251             final Fix removeImport = RemoveUnusedImportFix.create(file, handle);
252             
253             allUnusedImports.add(handle);
254             errors.add(ErrorDescriptionFactory.createErrorDescription(Severity.VERIFIER, "Unused import", new FixAllImportsFixList(removeImport, removeAllUnusedImports, allUnusedImports), doc, line));
255         }
256         
257         for (Element decl : v.type2Uses.keySet()) {
258             if (isCancelled())
259                 return Collections.emptySet();
260             
261             List JavaDoc<Use> uses = v.type2Uses.get(decl);
262             
263             for (Use u : uses) {
264                 if (u.spec == null)
265                     continue;
266                 
267                 if (u.type.contains(UseTypes.Element) && org.netbeans.modules.java.editor.semantic.Utilities.isPrivateElement(decl)) {
268                     if (decl.getKind().isField() || isLocalVariableClosure(decl)) {
269                         if (!hasAllTypes(uses, EnumSet.of(UseTypes.READ, UseTypes.WRITE))) {
270                             u.spec.add(ColoringAttributes.UNUSED);
271                         }
272                     }
273                     
274                     if (decl.getKind() == ElementKind.CONSTRUCTOR || decl.getKind() == ElementKind.METHOD) {
275                         if (!hasAllTypes(uses, EnumSet.of(UseTypes.EXECUTE))) {
276                             u.spec.add(ColoringAttributes.UNUSED);
277                         }
278                     }
279                     
280                     if (decl.getKind().isClass() || decl.getKind().isInterface()) {
281                         if (!hasAllTypes(uses, EnumSet.of(UseTypes.CLASS_USE))) {
282                             u.spec.add(ColoringAttributes.UNUSED);
283                         }
284                     }
285                 }
286                 
287                 Collection JavaDoc<ColoringAttributes> c = EnumSet.copyOf(u.spec);
288                 Highlight h = Utilities.createHighlight(cu, info.getTrees().getSourcePositions(), doc, u.tree, c, null);
289                 
290                 if (h != null) {
291                     result.add(h);
292                 }
293             }
294         }
295             
296         if (isCancelled())
297             return Collections.emptySet();
298         
299         ERROR_DESCRIPTION_SETTER.setErrors(doc, errors);
300         
301         TimesCollector.getDefault().reportTime(((DataObject) doc.getProperty(Document.StreamDescriptionProperty)).getPrimaryFile(), "semantic", "Semantic", (System.currentTimeMillis() - start));
302         
303         return result;
304     }
305     
306     private boolean hasAllTypes(List JavaDoc<Use> uses, Collection JavaDoc<UseTypes> types) {
307         EnumSet JavaDoc e = EnumSet.copyOf(types);
308         
309         for (Use u : uses) {
310             if (types.isEmpty()) {
311                 return true;
312             }
313             
314             types.removeAll(u.type);
315         }
316         
317         return types.isEmpty();
318     }
319     
320     private enum UseTypes {
321         READ, WRITE, EXECUTE, Element, CLASS_USE;
322     }
323     
324     private static boolean isLocalVariableClosure(Element el) {
325         return el.getKind() == ElementKind.PARAMETER || el.getKind() == ElementKind.LOCAL_VARIABLE || el.getKind() == ElementKind.EXCEPTION_PARAMETER;
326     }
327         
328     private static class Use {
329         private Collection JavaDoc<UseTypes> type;
330         private TreePath tree;
331         private Collection JavaDoc<ColoringAttributes> spec;
332         
333         public Use(Collection JavaDoc<UseTypes> type, TreePath tree, Collection JavaDoc<ColoringAttributes> spec) {
334             this.type = type;
335             this.tree = tree;
336             this.spec = spec;
337         }
338         
339         public String JavaDoc toString() {
340             return "Use: " + type;
341         }
342     }
343     
344     private static class DetectorVisitor extends CancellableTreePathScanner<Void JavaDoc, EnumSet JavaDoc<UseTypes>> {
345         
346         private org.netbeans.api.java.source.CompilationInfo info;
347         private Document JavaDoc doc;
348         private Map JavaDoc<Element, List JavaDoc<Use>> type2Uses;
349         private Map JavaDoc<Element, TreePath/*ImportTree*/> type2Highlight;
350 // private Set<Highlight> highlights;
351

352 // private int pos;
353
private SourcePositions sourcePositions;
354         
355         private DetectorVisitor(org.netbeans.api.java.source.CompilationInfo info, Document JavaDoc doc/*, int pos*/) {
356             this.info = info;
357             this.doc = doc;
358             type2Uses = new HashMap JavaDoc<Element, List JavaDoc<Use>>();
359             this.type2Highlight = new HashMap JavaDoc<Element, TreePath/*ImportTree*/>();
360 // this.pos = pos;
361
}
362         
363         private Highlight createHighlight(CompilationUnitTree cu, SourcePositions sp, TreePath tree, Collection JavaDoc<ColoringAttributes> c, Color JavaDoc es) {
364             return Utilities.createHighlight(cu, sp, doc, tree, c, es);
365         }
366         
367         @Override JavaDoc
368         public Void JavaDoc visitAssignment(AssignmentTree tree, EnumSet JavaDoc<UseTypes> d) {
369             handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getVariable()), EnumSet.of(UseTypes.WRITE));
370             
371             Tree expr = tree.getExpression();
372             
373             if (expr instanceof IdentifierTree) {
374                 TreePath tp = new TreePath(getCurrentPath(), expr);
375                 resolveType(tp);
376                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ));
377             }
378             
379             scan(tree.getVariable(), EnumSet.of(UseTypes.WRITE));
380             scan(tree.getExpression(), null);
381             
382             return super.visitAssignment(tree, null);
383         }
384
385         @Override JavaDoc
386         public Void JavaDoc visitCompoundAssignment(CompoundAssignmentTree tree, EnumSet JavaDoc<UseTypes> d) {
387             handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getVariable()), EnumSet.of(UseTypes.WRITE));
388             
389             Tree expr = tree.getExpression();
390             
391             if (expr instanceof IdentifierTree) {
392                 TreePath tp = new TreePath(getCurrentPath(), expr);
393                 resolveType(tp);
394                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ));
395             }
396             
397             scan(tree.getVariable(), EnumSet.of(UseTypes.WRITE));
398             scan(tree.getExpression(), null);
399             
400             return super.visitCompoundAssignment(tree, null);
401         }
402
403         @Override JavaDoc
404         public Void JavaDoc visitReturn(ReturnTree tree, EnumSet JavaDoc<UseTypes> d) {
405             if (tree.getExpression() instanceof IdentifierTree) {
406                 handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
407             }
408             
409             super.visitReturn(tree, null);
410             return null;
411         }
412         
413         @Override JavaDoc
414         public Void JavaDoc visitMemberSelect(MemberSelectTree tree, EnumSet JavaDoc<UseTypes> d) {
415             Tree expr = tree.getExpression();
416             
417             if (expr instanceof IdentifierTree) {
418                 TreePath tp = new TreePath(getCurrentPath(), expr);
419                 resolveType(tp);
420                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ));
421             }
422             
423             Element el = info.getTrees().getElement(getCurrentPath());
424             
425             if (el != null && el.getKind().isField()) {
426                 handlePossibleIdentifier(getCurrentPath(), EnumSet.of(UseTypes.READ));
427             }
428 // System.err.println("XXXX=" + tree.toString());
429
// System.err.println("YYYY=" + info.getElement(tree));
430

431             super.visitMemberSelect(tree, null);
432             return null;
433         }
434         
435         private void addModifiers(Element decl, Collection JavaDoc<ColoringAttributes> c) {
436             if (decl.getModifiers().contains(Modifier.STATIC)) {
437                 c.add(ColoringAttributes.STATIC);
438             }
439             
440             if (decl.getModifiers().contains(Modifier.ABSTRACT)) {
441                 c.add(ColoringAttributes.ABSTRACT);
442             }
443             
444             boolean accessModifier = false;
445             
446             if (decl.getModifiers().contains(Modifier.PUBLIC)) {
447                 c.add(ColoringAttributes.PUBLIC);
448                 accessModifier = true;
449             }
450             
451             if (decl.getModifiers().contains(Modifier.PROTECTED)) {
452                 c.add(ColoringAttributes.PROTECTED);
453                 accessModifier = true;
454             }
455             
456             if (decl.getModifiers().contains(Modifier.PRIVATE)) {
457                 c.add(ColoringAttributes.PRIVATE);
458                 accessModifier = true;
459             }
460             
461             if (!accessModifier && !isLocalVariableClosure(decl)) {
462                 c.add(ColoringAttributes.PACKAGE_PRIVATE);
463             }
464             
465             if (info.getElements().isDeprecated(decl)) {
466                 c.add(ColoringAttributes.DEPRECATED);
467             }
468         }
469         
470         private Collection JavaDoc<ColoringAttributes> getMethodColoring(ExecutableElement mdecl) {
471             Collection JavaDoc<ColoringAttributes> c = new ArrayList JavaDoc<ColoringAttributes>();
472             
473             addModifiers(mdecl, c);
474             
475             if (mdecl.getKind() == ElementKind.CONSTRUCTOR)
476                 c.add(ColoringAttributes.CONSTRUCTOR);
477             else
478                 c.add(ColoringAttributes.METHOD);
479             
480             return c;
481         }
482         
483         private Collection JavaDoc<ColoringAttributes> getVariableColoring(Element decl) {
484             Collection JavaDoc<ColoringAttributes> c = new ArrayList JavaDoc<ColoringAttributes>();
485             
486             addModifiers(decl, c);
487             
488             if (decl.getKind().isField()) {
489                 c.add(ColoringAttributes.FIELD);
490                 
491                 return c;
492             }
493             
494             if (decl.getKind() == ElementKind.LOCAL_VARIABLE || decl.getKind() == ElementKind.EXCEPTION_PARAMETER) {
495                 c.add(ColoringAttributes.LOCAL_VARIABLE);
496                 
497                 return c;
498             }
499             
500             if (decl.getKind() == ElementKind.PARAMETER) {
501                 c.add(ColoringAttributes.PARAMETER);
502                 
503                 return c;
504             }
505             
506             assert false;
507             
508             return null;
509         }
510
511         private static final Set JavaDoc<Kind> LITERALS = EnumSet.of(Kind.BOOLEAN_LITERAL, Kind.CHAR_LITERAL, Kind.DOUBLE_LITERAL, Kind.FLOAT_LITERAL, Kind.INT_LITERAL, Kind.LONG_LITERAL, Kind.STRING_LITERAL);
512
513         private void handlePossibleIdentifier(TreePath expr, Collection JavaDoc<UseTypes> type) {
514             handlePossibleIdentifier(expr, type, null, false);
515         }
516         
517         private void handlePossibleIdentifier(TreePath expr, Collection JavaDoc<UseTypes> type, Element decl, boolean providesDecl) {
518             
519             if (Utilities.isKeyword(expr.getLeaf())) {
520                 //ignore keywords:
521
return ;
522             }
523
524             if (expr.getLeaf().getKind() == Kind.PRIMITIVE_TYPE) {
525                 //ignore primitive types:
526
return ;
527             }
528
529             if (LITERALS.contains(expr.getLeaf().getKind())) {
530                 //ignore literals:
531
return ;
532             }
533
534             decl = !providesDecl ? info.getTrees().getElement(expr) : decl;
535             
536             Collection JavaDoc<ColoringAttributes> c = null;
537             
538             //causes NPE later, as decl is put into list of declarations to handle:
539
// if (decl == null) {
540
// c = Collections.singletonList(ColoringAttributes.UNDEFINED);
541
// }
542

543             if (decl != null && (decl.getKind().isField() || isLocalVariableClosure(decl))) {
544                 c = getVariableColoring(decl);
545             }
546             
547             if (decl != null && decl instanceof ExecutableElement) {
548                 c = getMethodColoring((ExecutableElement) decl);
549             }
550             
551             if (decl != null && (decl.getKind().isClass() || decl.getKind().isInterface())) {
552                 //class use make look like read variable access:
553
if (type.contains(UseTypes.READ)) {
554                     type.remove(UseTypes.READ);
555                     type.add(UseTypes.CLASS_USE);
556                 }
557                 
558                 c = new ArrayList JavaDoc<ColoringAttributes>();
559                 
560                 addModifiers(decl, c);
561             }
562             
563             if (c != null) {
564                 addUse(decl, type, expr, c);
565             }
566         }
567         
568         private void addUse(Element decl, Collection JavaDoc<UseTypes> useTypes, TreePath t, Collection JavaDoc<ColoringAttributes> c) {
569             List JavaDoc<Use> uses = type2Uses.get(decl);
570             
571             if (uses == null) {
572                 type2Uses.put(decl, uses = new ArrayList JavaDoc<Use>());
573             }
574             
575             Use u = new Use(useTypes, t, c);
576             
577             uses.add(u);
578         }
579
580         @Override JavaDoc
581         public Void JavaDoc visitTypeCast(TypeCastTree tree, EnumSet JavaDoc<UseTypes> d) {
582             resolveType(new TreePath(getCurrentPath(), tree.getType()));
583             
584             Tree expr = tree.getExpression();
585             
586             if (expr instanceof IdentifierTree) {
587                 handlePossibleIdentifier(new TreePath(getCurrentPath(), expr), EnumSet.of(UseTypes.READ));
588             }
589             
590             super.visitTypeCast(tree, d);
591             return null;
592         }
593
594         @Override JavaDoc
595         public Void JavaDoc visitInstanceOf(InstanceOfTree tree, EnumSet JavaDoc<UseTypes> d) {
596             Tree expr = tree.getExpression();
597             
598             if (expr instanceof IdentifierTree) {
599                 handlePossibleIdentifier(new TreePath(getCurrentPath(), expr), EnumSet.of(UseTypes.READ));
600             }
601             
602             TreePath tp = new TreePath(getCurrentPath(), tree.getType());
603             resolveType(tp);
604             handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
605             
606             super.visitInstanceOf(tree, null);
607             
608             //TODO: should be considered
609
return null;
610         }
611
612         @Override JavaDoc
613         public Void JavaDoc visitCompilationUnit(CompilationUnitTree tree, EnumSet JavaDoc<UseTypes> d) {
614         scan(tree.getPackageAnnotations(), d);
615         //ignore package X.Y.Z;:
616
//scan(tree.getPackageDecl(), p);
617
scan(tree.getImports(), d);
618         scan(tree.getTypeDecls(), d);
619         return null;
620         }
621
622         @Override JavaDoc
623         public Void JavaDoc visitMethodInvocation(MethodInvocationTree tree, EnumSet JavaDoc<UseTypes> d) {
624             Tree possibleIdent = tree.getMethodSelect();
625             boolean handled = false;
626             
627             if (possibleIdent.getKind() == Kind.IDENTIFIER) {
628                 //handle "this" and "super" constructors:
629
String JavaDoc ident = ((IdentifierTree) possibleIdent).getName().toString();
630                 
631                 if ("super".equals(ident) || "this".equals(ident)) { //NOI18N
632
Element resolved = info.getTrees().getElement(getCurrentPath());
633                     
634                     addUse(resolved, EnumSet.of(UseTypes.EXECUTE), null, null);
635                     handled = true;
636                 }
637             }
638             
639             if (!handled) {
640                 handlePossibleIdentifier(new TreePath(getCurrentPath(), possibleIdent), EnumSet.of(UseTypes.EXECUTE));
641             }
642             
643             for (Tree expr : tree.getArguments()) {
644                 if (expr instanceof IdentifierTree) {
645                     handlePossibleIdentifier(new TreePath(getCurrentPath(), expr), EnumSet.of(UseTypes.READ));
646                 }
647             }
648             for (Tree expr : tree.getTypeArguments()) {
649                 if (expr instanceof IdentifierTree) {
650                     resolveType(new TreePath(getCurrentPath(), expr));
651                 }
652             }
653             
654             super.visitMethodInvocation(tree, null);
655             return null;
656         }
657
658         @Override JavaDoc
659         public Void JavaDoc visitIdentifier(IdentifierTree tree, EnumSet JavaDoc<UseTypes> d) {
660 // if ("l".equals(tree.toString())) {
661
// Thread.dumpStack();
662
// }
663
// handlePossibleIdentifier(tree);
664
// //also possible type: (like in Collections.EMPTY_LIST):
665
// resolveType(tree);
666
// Thread.dumpStack();
667

668             if (d != null) {
669                 handlePossibleIdentifier(getCurrentPath(), d);
670             }
671             super.visitIdentifier(tree, null);
672             return null;
673         }
674 //
675
@Override JavaDoc
676         public Void JavaDoc visitMethod(MethodTree tree, EnumSet JavaDoc<UseTypes> d) {
677 // Element decl = pi.getAttribution().getElement(tree);
678
//
679
// if (decl != null) {
680
// assert decl instanceof ExecutableElement;
681
//
682
// Coloring c = getMethodColoring((ExecutableElement) decl);
683
// HighlightImpl h = createHighlight(decl.getSimpleName(), tree, c, null);
684
//
685
// if (h != null) {
686
// highlights.add(h);
687
// }
688
// }
689
handlePossibleIdentifier(getCurrentPath(), EnumSet.of(UseTypes.Element));
690             
691             for (Tree t : tree.getThrows()) {
692                 TreePath tp = new TreePath(getCurrentPath(), t);
693                 resolveType(tp);
694                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
695             }
696             
697             if (tree.getReturnType() != null)
698                 resolveType(new TreePath(getCurrentPath(), tree.getReturnType()));
699            
700             EnumSet JavaDoc<UseTypes> paramsUseTypes;
701             
702             Element el = info.getTrees().getElement(getCurrentPath());
703             
704             if (el != null && el.getModifiers().contains(Modifier.ABSTRACT)) {
705                 paramsUseTypes = EnumSet.of(UseTypes.WRITE, UseTypes.READ);
706             } else {
707                 paramsUseTypes = EnumSet.of(UseTypes.WRITE);
708             }
709         
710             scan(tree.getModifiers(), null);
711             scan(tree.getReturnType(), EnumSet.of(UseTypes.CLASS_USE));
712             scan(tree.getTypeParameters(), null);
713             scan(tree.getParameters(), paramsUseTypes);
714             scan(tree.getThrows(), null);
715             scan(tree.getBody(), null);
716         
717             return null;
718         }
719
720         @Override JavaDoc
721         public Void JavaDoc visitExpressionStatement(ExpressionStatementTree tree, EnumSet JavaDoc<UseTypes> d) {
722 // if (tree instanceof IdentifierTree) {
723
// handlePossibleIdentifier(tree, EnumSet.of(UseTypes.READ));
724
// }
725

726             super.visitExpressionStatement(tree, null);
727             return null;
728         }
729
730         @Override JavaDoc
731         public Void JavaDoc visitParenthesized(ParenthesizedTree tree, EnumSet JavaDoc<UseTypes> d) {
732             ExpressionTree expr = tree.getExpression();
733             
734             if (expr instanceof IdentifierTree) {
735                 handlePossibleIdentifier(new TreePath(getCurrentPath(), expr), EnumSet.of(UseTypes.READ));
736             }
737             
738             super.visitParenthesized(tree, null);
739             return null;
740         }
741
742         @Override JavaDoc
743         public Void JavaDoc visitEnhancedForLoop(EnhancedForLoopTree tree, EnumSet JavaDoc<UseTypes> d) {
744             scan(tree.getVariable(), EnumSet.of(UseTypes.WRITE));
745             
746             if (tree.getExpression().getKind() == Kind.IDENTIFIER)
747                 handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
748             
749             scan(tree.getExpression(), null);
750             scan(tree.getStatement(), null);
751             
752             return null;
753         }
754         
755         @Override JavaDoc
756         public Void JavaDoc visitImport(ImportTree tree, EnumSet JavaDoc<UseTypes> d) {
757             if (!tree.isStatic()) {
758                 Element decl = info.getTrees().getElement(new TreePath(getCurrentPath(), tree.getQualifiedIdentifier()));
759                 
760                 if (decl != null && decl.asType().getKind() != TypeKind.ERROR) { //unresolvable imports should not be marked as unused
761
type2Highlight.put(decl, getCurrentPath());
762                 }
763 // } else {
764
// //cannot handle package import for now.
765
// //cannot handle static imports for now.
766
// }
767
}
768             super.visitImport(tree, null);
769             return null;
770         }
771         
772         private String JavaDoc getSimple(String JavaDoc fqn) {
773             int lastDot = fqn.lastIndexOf('.');
774             
775             if (lastDot != (-1)) {
776                 return fqn.substring(lastDot + 1);
777             } else {
778                 return fqn;
779             }
780         }
781         
782         @Override JavaDoc
783         public Void JavaDoc visitVariable(VariableTree tree, EnumSet JavaDoc<UseTypes> d) {
784             TreePath type = new TreePath(getCurrentPath(), tree.getType());
785             
786             if (type.getLeaf() instanceof ArrayTypeTree) {
787                 type = new TreePath(type, ((ArrayTypeTree) type.getLeaf()).getType());
788             }
789             
790             resolveType(type);
791             
792             if (type.getLeaf().getKind() == Kind.IDENTIFIER)
793                 handlePossibleIdentifier(type, EnumSet.of(UseTypes.CLASS_USE));
794             
795             Collection JavaDoc<UseTypes> uses = null;
796             boolean isParameter = false;
797             
798             if (tree.getInitializer() != null) {
799                 uses = EnumSet.of(UseTypes.Element, UseTypes.WRITE);
800                 if (tree.getInitializer().getKind() == Kind.IDENTIFIER)
801                     handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getInitializer()), EnumSet.of(UseTypes.READ));
802             } else {
803                 Element e = info.getTrees().getElement(getCurrentPath());
804                 
805                 if (e != null && e.getKind() == ElementKind.FIELD) {
806                     uses = EnumSet.of(UseTypes.Element, UseTypes.WRITE);
807                 } else {
808                     uses = EnumSet.of(UseTypes.Element);
809                 }
810             }
811             
812             if (d != null) {
813                 Set JavaDoc<UseTypes> ut = new HashSet JavaDoc();
814                 
815                 ut.addAll(uses);
816                 ut.addAll(d);
817                 
818                 uses = EnumSet.copyOf(ut);
819             }
820             
821             handlePossibleIdentifier(getCurrentPath(), uses);
822             
823             super.visitVariable(tree, null);
824             return null;
825         }
826         
827         private boolean isParameter(VariableTree var, MethodTree decl) {
828             for (VariableTree declVar : decl.getParameters()) {
829                 if (var == declVar)
830                     return true;
831             }
832             
833             return false;
834         }
835         
836         @Override JavaDoc
837         public Void JavaDoc visitAnnotation(AnnotationTree tree, EnumSet JavaDoc<UseTypes> d) {
838 // System.err.println("tree.getType()= " + tree.toString());
839
// System.err.println("tree.getType()= " + tree.getClass());
840
//
841
TreePath tp = new TreePath(getCurrentPath(), tree.getAnnotationType());
842             resolveType(tp);
843             handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
844             super.visitAnnotation(tree, EnumSet.noneOf(UseTypes.class));
845             //TODO: maybe should be considered
846
return null;
847         }
848
849         @Override JavaDoc
850         public Void JavaDoc visitNewClass(NewClassTree tree, EnumSet JavaDoc<UseTypes> d) {
851             TreePath tp;
852             Tree ident = tree.getIdentifier();
853             
854             if (ident.getKind() == Kind.PARAMETERIZED_TYPE) {
855                 tp = new TreePath(new TreePath(getCurrentPath(), ident), ((ParameterizedTypeTree) ident).getType());
856             } else {
857                 tp = new TreePath(getCurrentPath(), ident);
858             }
859             
860             resolveType(tp);
861         handlePossibleIdentifier(tp, EnumSet.of(UseTypes.EXECUTE), info.getTrees().getElement(getCurrentPath()), true);
862             
863             Element clazz = info.getTrees().getElement(tp);
864             
865             if (clazz != null) {
866                 addUse(clazz, EnumSet.of(UseTypes.CLASS_USE), null, null);
867             }
868         
869             for (Tree expr : tree.getArguments()) {
870                 if (expr instanceof IdentifierTree) {
871                     handlePossibleIdentifier(new TreePath(getCurrentPath(), expr), EnumSet.of(UseTypes.READ));
872                 }
873             }
874             
875             super.visitNewClass(tree, null);
876             
877             return null;
878         }
879
880         @Override JavaDoc
881         public Void JavaDoc visitParameterizedType(ParameterizedTypeTree tree, EnumSet JavaDoc<UseTypes> d) {
882             if (getCurrentPath().getParentPath().getLeaf().getKind() != Kind.NEW_CLASS) {
883                 //NewClass has already been handled as part of visitNewClass:
884
TreePath tp = new TreePath(getCurrentPath(), tree.getType());
885                 resolveType(tp);
886                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
887             }
888             
889             for (Tree t : tree.getTypeArguments()) {
890                 TreePath tp = new TreePath(getCurrentPath(), t);
891                 resolveType(tp);
892                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
893                 
894 // HighlightImpl h = createHighlight("", t, TYPE_PARAMETER);
895
//
896
// if (h != null)
897
// highlights.add(h);
898
}
899             
900             super.visitParameterizedType(tree, null);
901             return null;
902         }
903
904         @Override JavaDoc
905         public Void JavaDoc visitBinary(BinaryTree tree, EnumSet JavaDoc<UseTypes> d) {
906             Tree left = tree.getLeftOperand();
907             Tree right = tree.getRightOperand();
908             
909             if (left instanceof IdentifierTree) {
910                 TreePath tp = new TreePath(getCurrentPath(), left);
911                 resolveType(tp);
912                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ));
913             }
914             
915             if (right instanceof IdentifierTree) {
916                 TreePath tp = new TreePath(getCurrentPath(), right);
917                 resolveType(tp);
918                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ));
919             }
920             
921             super.visitBinary(tree, null);
922             return null;
923         }
924
925         @Override JavaDoc
926         public Void JavaDoc visitClass(ClassTree tree, EnumSet JavaDoc<UseTypes> d) {
927             Tree extnds = tree.getExtendsClause();
928             
929             if (extnds != null) {
930                 TreePath tp = new TreePath(getCurrentPath(), extnds);
931                 resolveType(tp);
932                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
933             }
934             
935             for (Tree t : tree.getImplementsClause()) {
936                 TreePath tp = new TreePath(getCurrentPath(), t);
937                 resolveType(tp);
938                 handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
939             }
940             
941             for (TypeParameterTree t : tree.getTypeParameters()) {
942                 for (Tree bound : t.getBounds()) {
943                     TreePath tp = new TreePath(new TreePath(getCurrentPath(), t), bound);
944                     resolveType(tp);
945                     handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
946                 }
947             }
948             
949             handlePossibleIdentifier(getCurrentPath(), EnumSet.of(UseTypes.Element));
950             
951             super.visitClass(tree, null);
952             //TODO: maybe should be considered
953
return null;
954         }
955         
956         @Override JavaDoc
957         public Void JavaDoc visitUnary(UnaryTree tree, EnumSet JavaDoc<UseTypes> d) {
958             if (tree.getExpression() instanceof IdentifierTree) {
959                 handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
960             }
961             super.visitUnary(tree, d);
962             return null;
963         }
964
965         @Override JavaDoc
966         public Void JavaDoc visitArrayAccess(ArrayAccessTree tree, EnumSet JavaDoc<UseTypes> d) {
967             if (tree.getExpression() != null && tree.getExpression().getKind() == Kind.IDENTIFIER) {
968                 handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
969             }
970             
971             if (tree.getIndex() instanceof IdentifierTree) {
972                 handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getIndex()), EnumSet.of(UseTypes.READ));
973             }
974             
975             super.visitArrayAccess(tree, null);
976             return null;
977         }
978
979         @Override JavaDoc
980         public Void JavaDoc visitNewArray(NewArrayTree tree, EnumSet JavaDoc<UseTypes> d) {
981             if (tree.getType() != null)
982                 resolveType(new TreePath(getCurrentPath(), tree.getType()));
983             
984             scan(tree.getType(), null);
985             scan(tree.getDimensions(), EnumSet.of(UseTypes.READ));
986             scan(tree.getInitializers(), EnumSet.of(UseTypes.READ));
987             
988             return null;
989         }
990         
991         @Override JavaDoc
992         public Void JavaDoc visitCatch(CatchTree tree, EnumSet JavaDoc<UseTypes> d) {
993             scan(tree.getParameter(), EnumSet.of(UseTypes.WRITE));
994             scan(tree.getBlock(), null);
995             return null;
996         }
997
998         @Override JavaDoc
999         public Void JavaDoc visitConditionalExpression(ConditionalExpressionTree node, EnumSet JavaDoc<UseTypes> p) {
1000            return super.visitConditionalExpression(node, EnumSet.of(UseTypes.READ));
1001        }
1002        
1003        @Override JavaDoc
1004        public Void JavaDoc visitAssert(AssertTree tree, EnumSet JavaDoc<UseTypes> p) {
1005            if (tree.getCondition().getKind() == Kind.IDENTIFIER)
1006                handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getCondition()), EnumSet.of(UseTypes.READ));
1007            if (tree.getDetail() != null && tree.getDetail().getKind() == Kind.IDENTIFIER)
1008                handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getDetail()), EnumSet.of(UseTypes.READ));
1009            
1010            return super.visitAssert(tree, null);
1011        }
1012        
1013        @Override JavaDoc
1014        public Void JavaDoc visitCase(CaseTree tree, EnumSet JavaDoc<UseTypes> p) {
1015            if (tree.getExpression() != null && tree.getExpression().getKind() == Kind.IDENTIFIER) {
1016                handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
1017            }
1018            
1019            return super.visitCase(tree, null);
1020        }
1021        
1022        @Override JavaDoc
1023        public Void JavaDoc visitThrow(ThrowTree tree, EnumSet JavaDoc<UseTypes> p) {
1024            if (tree.getExpression() != null && tree.getExpression().getKind() == Kind.IDENTIFIER) {
1025                handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ));
1026            }
1027            
1028            return super.visitThrow(tree, p);
1029        }
1030
1031        @Override JavaDoc
1032        public Void JavaDoc visitTypeParameter(TypeParameterTree tree, EnumSet JavaDoc<UseTypes> p) {
1033            for (Tree bound : tree.getBounds()) {
1034                if (bound.getKind() == Kind.IDENTIFIER) {
1035                    TreePath tp = new TreePath(getCurrentPath(), bound);
1036                    
1037                    handlePossibleIdentifier(tp, EnumSet.of(UseTypes.CLASS_USE));
1038                    resolveType(tp);
1039                }
1040            }
1041            return super.visitTypeParameter(tree, p);
1042        }
1043        
1044        private void resolveType(TreePath type) {
1045            FirstIdentTypeVisitor v = new FirstIdentTypeVisitor();
1046            
1047            v.scan(type, null);
1048            
1049            if (v.first == null)
1050                return ;
1051            
1052            Element decl = info.getTrees().getElement(v.first);
1053            
1054            if (decl == null) {
1055// System.err.println("Warning: type=" + type);
1056
// System.err.println("decl=" + decl);
1057

1058                return ;
1059            }
1060            
1061            type2Highlight.remove(decl);
1062        }
1063        
1064        private static class FirstIdentTypeVisitor extends TreePathScanner<Void JavaDoc, Void JavaDoc> {
1065            private TreePath first = null;
1066            
1067            public Void JavaDoc visitIdentifier(IdentifierTree tree, Void JavaDoc d) {
1068                if (first == null) {
1069                    first = getCurrentPath();
1070                }
1071                
1072                return super.visitIdentifier(tree, null);
1073            }
1074            
1075        }
1076    }
1077    
1078    public static interface ErrorDescriptionSetter {
1079        
1080        public void setErrors(Document JavaDoc doc, List JavaDoc<ErrorDescription> errors);
1081        
1082    }
1083    
1084    static ErrorDescriptionSetter ERROR_DESCRIPTION_SETTER = new ErrorDescriptionSetter() {
1085        
1086        public void setErrors(Document JavaDoc doc, List JavaDoc<ErrorDescription> errors) {
1087            HintsController.setErrors(doc, "semantic-highlighter", errors);
1088        }
1089        
1090    };
1091
1092}
1093
Popular Tags