KickJava   Java API By Example, From Geeks To Geeks.

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


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-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.editor.semantic;
20
21 import com.sun.source.tree.IdentifierTree;
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.CompilationUnitTree;
24 import com.sun.source.tree.MemberSelectTree;
25 import com.sun.source.tree.MethodTree;
26 import com.sun.source.tree.Tree;
27 import com.sun.source.tree.Tree.Kind;
28 import com.sun.source.tree.VariableTree;
29 import com.sun.source.util.SourcePositions;
30 import com.sun.source.util.TreePath;
31 import java.awt.Color JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collection JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.logging.Level JavaDoc;
37 import javax.swing.text.BadLocationException JavaDoc;
38 import javax.swing.text.Document JavaDoc;
39 import javax.swing.text.Position JavaDoc;
40 import javax.swing.text.Position.Bias;
41 import java.util.HashSet JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.Set JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46 import javax.lang.model.element.Element;
47 import javax.lang.model.element.ElementKind;
48 import javax.lang.model.element.Modifier;
49 import javax.lang.model.element.Name;
50 import org.netbeans.modules.editor.highlights.spi.Highlight;
51 import org.openide.text.NbDocument;
52 import org.openide.util.Exceptions;
53
54 /**
55  *
56  * @author Jan Lahoda
57  */

58 public class Utilities {
59     
60     private static final Logger JavaDoc LOG = Logger.getLogger(Utilities.class.getName());
61     
62     @Deprecated JavaDoc
63     private static final boolean DEBUG = false;
64     
65     private static final int[] NO_SPAN = {-1, -1};
66     
67     /** Creates a new instance of Utilities */
68     public Utilities() {
69     }
70     
71     private static int[] findIdentifierSpanImpl(Tree decl, Tree lastLeft, String JavaDoc name, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
72         return findIdentifierSpanImpl(decl, lastLeft, Collections.<Tree>emptyList(), name, cu, positions, doc);
73     }
74
75     private static int[] findIdentifierSpanImpl(Tree decl, Tree lastLeft, List JavaDoc<? extends Tree> firstRight, String JavaDoc name, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
76         int declStart = (int) positions.getStartPosition(cu, decl);
77         int start = lastLeft != null ? (int)positions.getEndPosition(cu, lastLeft) : declStart;
78         
79         if (start == (-1)) {
80             start = declStart;
81             if (start == (-1)) {
82                 return NO_SPAN;
83             }
84         }
85         
86         try {
87             int end = (int)positions.getEndPosition(cu, decl);
88
89             for (Tree t : firstRight) {
90                 if (t == null)
91                     continue;
92
93                 int proposedEnd = (int)positions.getStartPosition(cu, t);
94
95                 if (proposedEnd != (-1) && proposedEnd < end)
96                     end = proposedEnd;
97             }
98             
99             if (end == (-1)) {
100                 return NO_SPAN;
101             }
102
103             if (start > end) {
104                 //may happend in case:
105
//public static String s() [] {}
106
//(meaning: method returning array of Strings)
107
//use a conservative start value:
108
start = (int) positions.getStartPosition(cu, decl);
109             }
110             
111             if (start > doc.getLength() || end > doc.getLength()) {
112                 if (DEBUG) {
113                     System.err.println("Log: position outside document: ");
114                     System.err.println("lastLeft = " + lastLeft );
115                     System.err.println("decl = " + decl);
116                     System.err.println("startOffset = " + start);
117                     System.err.println("endOffset = " + end);
118                     Thread.dumpStack();
119                 }
120                 
121                 return NO_SPAN;
122             }
123             
124             String JavaDoc text = doc.getText(start, end - start);
125             
126             int index = text.lastIndexOf(name.toString());
127             
128             if (index != (-1)) {
129                 return new int[] {start + index, start + index + name.length()};
130             }
131         } catch (BadLocationException JavaDoc e) {
132             LOG.log(Level.INFO, null, e);
133         }
134         
135         return NO_SPAN;
136     }
137     
138     private static int[] findIdentifierSpanImpl(MemberSelectTree tree, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
139         int start = (int)positions.getStartPosition(cu, tree);
140         
141         int endPosition = (int)positions.getEndPosition(cu, tree);
142         
143         if (start == (-1) || endPosition == (-1))
144             return NO_SPAN;
145
146         try {
147             String JavaDoc member = tree.getIdentifier().toString();
148             int end = endPosition - start;
149             
150             if (start > doc.getLength() || end > doc.getLength()) {
151                 if (DEBUG) {
152                     System.err.println("Log: position outside document: ");
153                     System.err.println("tree = " + tree );
154                     System.err.println("member = " + member);
155                     System.err.println("startOffset = " + start);
156                     System.err.println("endOffset = " + end);
157                     Thread.dumpStack();
158                 }
159                 
160                 return NO_SPAN;
161             }
162             
163             String JavaDoc text = doc.getText(start, end);
164             
165             int index = text.lastIndexOf(member);
166             
167             if (index != (-1)) {
168                 return new int[] {start + index, start + index + member.length()};
169             }
170         } catch (BadLocationException JavaDoc e) {
171             BadLocationException JavaDoc ex = Exceptions.attachMessage(e, "start=" + start + ", endPosition=" + endPosition);
172             LOG.log(Level.INFO, null, ex);
173         }
174         
175         return NO_SPAN;
176     }
177     
178     private static final Map JavaDoc<Class JavaDoc, List JavaDoc<Kind>> class2Kind;
179     
180     static {
181         class2Kind = new HashMap JavaDoc<Class JavaDoc, List JavaDoc<Kind>>();
182         
183         for (Kind k : Kind.values()) {
184             Class JavaDoc c = k.asInterface();
185             List JavaDoc<Kind> kinds = class2Kind.get(c);
186             
187             if (kinds == null) {
188                 class2Kind.put(c, kinds = new ArrayList JavaDoc<Kind>());
189             }
190             
191             kinds.add(k);
192         }
193     }
194     
195     private static int[] findIdentifierSpanImpl(TreePath decl, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
196         if (doc == null) {
197             throw new NullPointerException JavaDoc();
198         }
199         
200         Tree leaf = decl.getLeaf();
201         
202         if (class2Kind.get(MethodTree.class).contains(leaf.getKind())) {
203             if (positions.getStartPosition(cu, leaf) == (-1) || positions.getEndPosition(cu, leaf) == (-1))
204                 return NO_SPAN; //syntetic methods
205

206             MethodTree method = (MethodTree) leaf;
207             List JavaDoc<Tree> rightTrees = new ArrayList JavaDoc<Tree>();
208
209             rightTrees.addAll(method.getParameters());
210             rightTrees.addAll(method.getThrows());
211             rightTrees.add(method.getBody());
212
213             Name name = method.getName();
214             
215             if (method.getReturnType() == null)
216                 name = ((ClassTree) decl.getParentPath().getLeaf()).getSimpleName();
217             
218             return findIdentifierSpanImpl(leaf, method.getReturnType(), rightTrees, name.toString(), cu, positions, doc);
219         }
220         if (class2Kind.get(VariableTree.class).contains(leaf.getKind())) {
221             VariableTree var = (VariableTree) leaf;
222
223             return findIdentifierSpanImpl(leaf, var.getType(), Collections.singletonList(var.getInitializer()), var.getName().toString(), cu, positions, doc);
224         }
225         if (class2Kind.get(MemberSelectTree.class).contains(leaf.getKind())) {
226             return findIdentifierSpanImpl((MemberSelectTree) leaf, cu, positions, doc);
227         }
228         if (class2Kind.get(ClassTree.class).contains(leaf.getKind())) {
229             //very inefficient:
230
int start = (int)positions.getStartPosition(cu, leaf);
231             int end = (int)positions.getEndPosition(cu, leaf);
232             
233             if (start == (-1) || end == (-1)) {
234                 return NO_SPAN;
235             }
236                 
237             if (start > doc.getLength() || end > doc.getLength()) {
238                 if (DEBUG) {
239                     System.err.println("Log: position outside document: ");
240                     System.err.println("decl = " + decl);
241                     System.err.println("startOffset = " + start);
242                     System.err.println("endOffset = " + end);
243                     Thread.dumpStack();
244                 }
245                 
246                 return NO_SPAN;
247             }
248             
249             String JavaDoc name = ((ClassTree) leaf).getSimpleName().toString();
250             
251             if (name.length() == 0)
252                 return NO_SPAN;
253             
254             try {
255                 String JavaDoc text = doc.getText(start, end - start);
256                 
257                 int index = text.indexOf(name);
258                 
259                 if (index == (-1)) {
260                     return NO_SPAN;
261 // throw new IllegalStateException("Should NEVER happen.");
262
}
263                 
264                 start += index;
265             } catch (BadLocationException JavaDoc e) {
266                 LOG.log(Level.INFO, null, e);
267             }
268             
269             int exactEnd = start + name.length();
270             
271             return new int[] {start, exactEnd};
272         }
273         throw new IllegalArgumentException JavaDoc("Only MethodDecl, VariableDecl and ClassDecl are accepted by this method.");
274     }
275
276     public static int[] findIdentifierSpan(final TreePath decl, final CompilationUnitTree cu, final SourcePositions positions, final Document JavaDoc doc) {
277         final int[][] result = new int[1][];
278         doc.render(new Runnable JavaDoc() {
279             public void run() {
280                 result[0] = findIdentifierSpanImpl(decl, cu, positions, doc);
281             }
282         });
283         
284         return result[0];
285     }
286     
287     private static int findBodyStartImpl(Tree cltree, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
288         int start = (int)positions.getStartPosition(cu, cltree);
289         int end = (int)positions.getEndPosition(cu, cltree);
290         
291         if (start == (-1) || end == (-1)) {
292             return -1;
293         }
294         
295         if (start > doc.getLength() || end > doc.getLength()) {
296             if (DEBUG) {
297                 System.err.println("Log: position outside document: ");
298                 System.err.println("decl = " + cltree);
299                 System.err.println("startOffset = " + start);
300                 System.err.println("endOffset = " + end);
301                 Thread.dumpStack();
302             }
303             
304             return (-1);
305         }
306         
307         try {
308             String JavaDoc text = doc.getText(start, end - start);
309             
310             int index = text.indexOf('{');
311             
312             if (index == (-1)) {
313                 return -1;
314 // throw new IllegalStateException("Should NEVER happen.");
315
}
316             
317             return start + index;
318         } catch (BadLocationException JavaDoc e) {
319             LOG.log(Level.INFO, null, e);
320         }
321         
322         return (-1);
323     }
324     
325     public static int findBodyStart(final Tree cltree, final CompilationUnitTree cu, final SourcePositions positions, final Document JavaDoc doc) {
326         Kind kind = cltree.getKind();
327         if (kind != Kind.CLASS && kind != Kind.METHOD)
328             throw new IllegalArgumentException JavaDoc("Unsupported kind: "+ kind);
329         final int[] result = new int[1];
330         
331         doc.render(new Runnable JavaDoc() {
332             public void run() {
333                 result[0] = findBodyStartImpl(cltree, cu, positions, doc);
334             }
335         });
336         
337         return result[0];
338     }
339     
340     private static int findLastBracketImpl(MethodTree tree, CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc) {
341         int start = (int)positions.getStartPosition(cu, tree);
342         int end = (int)positions.getEndPosition(cu, tree);
343         
344         if (start == (-1) || end == (-1)) {
345             return -1;
346         }
347         
348         if (start > doc.getLength() || end > doc.getLength()) {
349             if (DEBUG) {
350                 System.err.println("Log: position outside document: ");
351                 System.err.println("decl = " + tree);
352                 System.err.println("startOffset = " + start);
353                 System.err.println("endOffset = " + end);
354                 Thread.dumpStack();
355             }
356             
357             return (-1);
358         }
359         
360         try {
361             String JavaDoc text = doc.getText(end - 1, 1);
362             
363             if (text.charAt(0) == '}')
364                 return end - 1;
365         } catch (BadLocationException JavaDoc e) {
366             LOG.log(Level.INFO, null, e);
367         }
368         
369         return (-1);
370     }
371     
372     public static int findLastBracket(final MethodTree tree, final CompilationUnitTree cu, final SourcePositions positions, final Document JavaDoc doc) {
373         final int[] result = new int[1];
374         
375         doc.render(new Runnable JavaDoc() {
376             public void run() {
377                 result[0] = findLastBracketImpl(tree, cu, positions, doc);
378             }
379         });
380         
381         return result[0];
382     }
383     
384     private static Highlight createHighlightImpl(CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc, int startOffset, int endOffset, Collection JavaDoc<ColoringAttributes> c, Color JavaDoc es) {
385         try {
386             if (startOffset > doc.getLength() || endOffset > doc.getLength()) {
387                 if (DEBUG) {
388                     System.err.println("Log: position outside document: ");
389 // System.err.println("tree = " + tree );
390
System.err.println("startOffset = " + startOffset );
391                     System.err.println("endOffset = " + endOffset );
392                     Thread.dumpStack();
393                 }
394                 
395                 return null;
396             }
397             
398             return new HighlightImpl(doc, startOffset, endOffset, c, es);
399         } catch (BadLocationException JavaDoc e) {
400             e.printStackTrace();
401             return null;
402         }
403     }
404     
405     private static Highlight createHighlightImpl(CompilationUnitTree cu, SourcePositions positions, Document JavaDoc doc, TreePath tree, Collection JavaDoc<ColoringAttributes> c, Color JavaDoc es) {
406         Tree leaf = tree.getLeaf();
407         int startOffset = (int)positions.getStartPosition(cu, leaf);
408         int endOffset = (int)positions.getEndPosition(cu, leaf);
409         
410         //XXX: do not use instanceof:
411
if (leaf instanceof MethodTree || leaf instanceof VariableTree || leaf instanceof ClassTree || leaf instanceof MemberSelectTree) {
412             int[] span = findIdentifierSpan(tree, cu, positions, doc);
413             
414             startOffset = span[0];
415             endOffset = span[1];
416         }
417         
418         if (startOffset == (-1) || endOffset == (-1))
419             return null;
420         
421         return createHighlightImpl(cu, positions, doc, startOffset, endOffset, c, es);
422     }
423     
424     public static Highlight createHighlight(final CompilationUnitTree cu, final SourcePositions positions, final Document JavaDoc doc, final TreePath tree, final Collection JavaDoc<ColoringAttributes> c, final Color JavaDoc es) {
425         final Highlight[] result = new Highlight[1];
426         
427         doc.render(new Runnable JavaDoc() {
428             public void run() {
429                 result[0] = createHighlightImpl(cu, positions, doc, tree, c, es);
430             }
431         });
432         
433         return result[0];
434     }
435     
436     public static Highlight createHighlight(final CompilationUnitTree cu, final SourcePositions positions, final Document JavaDoc doc, final int startOffset, final int endOffset, final Collection JavaDoc<ColoringAttributes> c, final Color JavaDoc es) {
437         final Highlight[] result = new Highlight[1];
438         
439         doc.render(new Runnable JavaDoc() {
440             public void run() {
441                 result[0] = createHighlightImpl(cu, positions, doc, startOffset, endOffset, c, es);
442             }
443         });
444         
445         return result[0];
446     }
447     
448     private static final Set JavaDoc<String JavaDoc> keywords;
449     
450     static {
451         keywords = new HashSet JavaDoc();
452         
453         keywords.add("true");
454         keywords.add("false");
455         keywords.add("null");
456         keywords.add("this");
457         keywords.add("super");
458         keywords.add("class");
459     }
460     
461     public static boolean isKeyword(Tree tree) {
462         if (tree.getKind() == Kind.IDENTIFIER) {
463             return keywords.contains(((IdentifierTree) tree).getName().toString());
464         }
465         if (tree.getKind() == Kind.MEMBER_SELECT) {
466             return keywords.contains(((MemberSelectTree) tree).getIdentifier().toString());
467         }
468         
469         return false;
470     }
471     
472     public static boolean isPrivateElement(Element el) {
473         if (el.getKind() == ElementKind.PARAMETER)
474             return true;
475         
476         if (el.getKind() == ElementKind.LOCAL_VARIABLE)
477             return true;
478         
479         if (el.getKind() == ElementKind.EXCEPTION_PARAMETER)
480             return true;
481         
482         return el.getModifiers().contains(Modifier.PRIVATE);
483     }
484     
485
486 }
487
Popular Tags