KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > java > 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
20 package org.netbeans.modules.editor.java;
21
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.EnhancedForLoopTree;
24 import com.sun.source.tree.Tree;
25 import com.sun.source.tree.VariableTree;
26 import com.sun.source.util.SourcePositions;
27 import com.sun.source.util.TreePath;
28 import com.sun.source.util.Trees;
29
30 import java.util.*;
31
32 import javax.lang.model.element.*;
33 import javax.lang.model.type.*;
34 import javax.lang.model.util.*;
35 import javax.swing.text.JTextComponent JavaDoc;
36
37 import org.netbeans.api.java.lexer.JavaTokenId;
38 import org.netbeans.api.lexer.TokenHierarchy;
39 import org.netbeans.api.lexer.TokenId;
40 import org.netbeans.api.lexer.TokenSequence;
41 import org.netbeans.editor.*;
42 import org.netbeans.editor.ext.ExtSettingsDefaults;
43 import org.netbeans.editor.ext.ExtSettingsNames;
44 import org.netbeans.editor.ext.java.JavaTokenContext;
45
46 /**
47  *
48  * @author Dusan Balek
49  */

50 public class Utilities {
51     
52     private static final String JavaDoc CAPTURED_WILDCARD = "<captured wildcard>"; //NOI18N
53
private static final String JavaDoc ERROR = "<error>"; //NOI18N
54
private static final String JavaDoc UNKNOWN = "<unknown>"; //NOI18N
55

56     private static boolean caseSensitive = true;
57     private static SettingsChangeListener settingsListener = new SettingsListener();
58     private static boolean inited;
59     
60
61     public static boolean startsWith(String JavaDoc theString, String JavaDoc prefix) {
62         if (theString == null || theString.length() == 0 || ERROR.equals(theString))
63             return false;
64         if (prefix == null || prefix.length() == 0)
65             return true;
66         return isCaseSensitive() ? theString.startsWith(prefix) :
67             theString.toLowerCase().startsWith(prefix.toLowerCase());
68     }
69     
70     public static boolean isCaseSensitive() {
71         lazyInit();
72         return caseSensitive;
73     }
74
75     public static void setCaseSensitive(boolean b) {
76         lazyInit();
77         caseSensitive = b;
78     }
79     
80     private static void lazyInit() {
81         if (!inited) {
82             inited = true;
83             Settings.addSettingsChangeListener(settingsListener);
84             setCaseSensitive(SettingsUtil.getBoolean(JavaKit.class,
85                     ExtSettingsNames.COMPLETION_CASE_SENSITIVE,
86                     ExtSettingsDefaults.defaultCompletionCaseSensitive));
87         }
88     }
89
90     public static TreePath getPathElementOfKind(Tree.Kind kind, TreePath path) {
91         return getPathElementOfKind(EnumSet.of(kind), path);
92     }
93     
94     public static TreePath getPathElementOfKind(EnumSet<Tree.Kind> kinds, TreePath path) {
95         while (path != null) {
96             if (kinds.contains(path.getLeaf().getKind()))
97                 return path;
98             path = path.getParentPath();
99         }
100         return null;
101     }
102     
103     public static boolean isJavaContext(final JTextComponent JavaDoc component, final int offset) {
104         TokenSequence<JavaTokenId> ts = getJavaTokenSequence(component, offset);
105         if (ts == null)
106             return false;
107         switch(ts.token().id()) {
108             case DOUBLE_LITERAL:
109                 if (ts.token().text().charAt(0) == '.')
110                     break;
111             case CHAR_LITERAL:
112             case FLOAT_LITERAL:
113             case FLOAT_LITERAL_INVALID:
114             case INT_LITERAL:
115             case INVALID_COMMENT_END:
116             case JAVADOC_COMMENT:
117             case LONG_LITERAL:
118             case STRING_LITERAL:
119             case LINE_COMMENT:
120             case BLOCK_COMMENT:
121                 return false;
122         }
123         return true;
124     }
125     
126     public static TokenSequence<JavaTokenId> getJavaTokenSequence(final JTextComponent JavaDoc component, final int offset) {
127         TokenHierarchy hierarchy = TokenHierarchy.get(component.getDocument());
128         if (hierarchy != null) {
129             TokenSequence<? extends TokenId> ts = hierarchy.tokenSequence();
130             while(ts != null && ts.moveNext()) {
131                 ts.move(offset);
132                 if (!ts.moveNext())
133                     ts.movePrevious();
134                 if (ts.language() == JavaTokenId.language())
135                     return (TokenSequence<JavaTokenId>)ts;
136                 ts = ts.embedded();
137             }
138         }
139         return null;
140     }
141     
142     public static CharSequence JavaDoc getTypeName(TypeMirror type, boolean fqn) {
143         return getTypeName(type, fqn, false);
144     }
145     
146     public static CharSequence JavaDoc getTypeName(TypeMirror type, boolean fqn, boolean varArg) {
147     if (type == null)
148             return ""; //NOI18N
149
return new TypeNameVisitor(varArg).visit(type, fqn);
150     }
151     
152     public static CharSequence JavaDoc getElementName(Element el, boolean fqn) {
153         if (el == null || el.asType().getKind() == TypeKind.NONE)
154             return ""; //NOI18N
155
return new ElementNameVisitor().visit(el, fqn);
156     }
157     
158     public static Collection<? extends Element> getForwardReferences(TreePath path, int pos, SourcePositions sourcePositions, Trees trees) {
159         HashSet<Element> refs = new HashSet<Element>();
160         while(path != null) {
161             switch(path.getLeaf().getKind()) {
162                 case BLOCK:
163                 case CLASS:
164                     return refs;
165                 case VARIABLE:
166                     refs.add(trees.getElement(path));
167                     TreePath parent = path.getParentPath();
168                     if (parent.getLeaf().getKind() == Tree.Kind.CLASS) {
169                         boolean isStatic = ((VariableTree)path.getLeaf()).getModifiers().getFlags().contains(Modifier.STATIC);
170                         for(Tree member : ((ClassTree)parent.getLeaf()).getMembers()) {
171                             if (member.getKind() == Tree.Kind.VARIABLE && sourcePositions.getStartPosition(path.getCompilationUnit(), member) >= pos &&
172                                     (isStatic || !((VariableTree)member).getModifiers().getFlags().contains(Modifier.STATIC)))
173                                 refs.add(trees.getElement(new TreePath(parent, member)));
174                         }
175                     }
176                     return refs;
177                 case ENHANCED_FOR_LOOP:
178                     EnhancedForLoopTree efl = (EnhancedForLoopTree)path.getLeaf();
179                     if (sourcePositions.getEndPosition(path.getCompilationUnit(), efl.getExpression()) >= pos)
180                         refs.add(trees.getElement(new TreePath(path, efl.getVariable())));
181             }
182             path = path.getParentPath();
183         }
184         return refs;
185     }
186     
187     public static List<String JavaDoc> varNamesSuggestions(TypeMirror type, String JavaDoc prefix, Types types, Elements elements, Iterable JavaDoc<? extends Element> locals, boolean isConst) {
188         List<String JavaDoc> result = new ArrayList<String JavaDoc>();
189         if (type == null)
190             return result;
191         List<String JavaDoc> vnct = varNamesForType(type, types, elements);
192         if (isConst) {
193             List<String JavaDoc> ls = new ArrayList<String JavaDoc>(vnct.size());
194             for (String JavaDoc s : vnct)
195                 ls.add(getConstName(s));
196             vnct = ls;
197         }
198         String JavaDoc p = prefix;
199         while (p != null && p.length() > 0) {
200             List<String JavaDoc> l = new ArrayList<String JavaDoc>();
201             for(String JavaDoc name : vnct)
202                 if (startsWith(name, p))
203                     l.add(name);
204             if (l.isEmpty()) {
205                 p = nextName(p);
206             } else {
207                 vnct = l;
208                 prefix = prefix.substring(0, prefix.length() - p.length());
209                 p = null;
210             }
211         }
212         for (String JavaDoc name : vnct) {
213             boolean isPrimitive = type.getKind().isPrimitive();
214             if (prefix != null && prefix.length() > 0) {
215                 if (isConst) {
216                     name = prefix.toUpperCase() + '_' + name;
217                 } else {
218                     name = prefix + Character.toUpperCase(name.charAt(0)) + name.substring(1);
219                 }
220             }
221             int cnt = 1;
222             while (isClashing(name, locals)) {
223                 if (isPrimitive) {
224                     char c = name.charAt(0);
225                     name = Character.toString(++c);
226                     if (c == 'z') //NOI18N
227
isPrimitive = false;
228                 } else {
229                     name += cnt++;
230                 }
231             }
232             result.add(name);
233         }
234         return result;
235     }
236
237     public static boolean isInMethod(TreePath tp) {
238         while (tp != null) {
239             if (tp.getLeaf().getKind() == Tree.Kind.METHOD) {
240                 return true;
241             }
242             
243             tp = tp.getParentPath();
244         }
245         
246         return false;
247     }
248         
249     private static List<String JavaDoc> varNamesForType(TypeMirror type, Types types, Elements elements) {
250         switch (type.getKind()) {
251             case ARRAY:
252                 TypeMirror iterable = types.getDeclaredType(elements.getTypeElement("java.lang.Iterable")); //NOI18N
253
TypeMirror ct = ((ArrayType)type).getComponentType();
254                 if (ct.getKind() == TypeKind.ARRAY && types.isSubtype(ct, iterable))
255                     return varNamesForType(ct, types, elements);
256                 List<String JavaDoc> vnct = new ArrayList<String JavaDoc>();
257                 for (String JavaDoc name : varNamesForType(ct, types, elements))
258                     vnct.add(name.endsWith("s") ? name + "es" : name + "s"); //NOI18N
259
return vnct;
260             case BOOLEAN:
261             case BYTE:
262             case CHAR:
263             case DOUBLE:
264             case FLOAT:
265             case INT:
266             case LONG:
267             case SHORT:
268                 return Collections.<String JavaDoc>singletonList(type.toString().substring(0, 1));
269             case TYPEVAR:
270                 return Collections.<String JavaDoc>singletonList(type.toString().toLowerCase());
271             case ERROR:
272                 String JavaDoc tn = ((ErrorType)type).asElement().getSimpleName().toString();
273                 if (tn.toUpperCase().contentEquals(tn))
274                     return Collections.<String JavaDoc>singletonList(tn.toLowerCase());
275                 StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
276                 ArrayList<String JavaDoc> al = new ArrayList<String JavaDoc>();
277                 if ("Iterator".equals(tn)) //NOI18N
278
al.add("it"); //NOI18N
279
while((tn = nextName(tn)).length() > 0) {
280                     al.add(tn);
281                     sb.append(tn.charAt(0));
282                 }
283                 if (sb.length() > 0)
284                     al.add(sb.toString());
285                 return al;
286             case DECLARED:
287                 iterable = types.getDeclaredType(elements.getTypeElement("java.lang.Iterable")); //NOI18N
288
tn = ((DeclaredType)type).asElement().getSimpleName().toString();
289                 if (tn.toUpperCase().contentEquals(tn))
290                     return Collections.<String JavaDoc>singletonList(tn.toLowerCase());
291                 sb = new StringBuilder JavaDoc();
292                 al = new ArrayList<String JavaDoc>();
293                 if ("Iterator".equals(tn)) //NOI18N
294
al.add("it"); //NOI18N
295
while((tn = nextName(tn)).length() > 0) {
296                     al.add(tn);
297                     sb.append(tn.charAt(0));
298                 }
299                 if (types.isSubtype(type, iterable)) {
300                     List<? extends TypeMirror> tas = ((DeclaredType)type).getTypeArguments();
301                     if (tas.size() > 0) {
302                         TypeMirror et = tas.get(0);
303                         if (et.getKind() == TypeKind.ARRAY || (et.getKind() != TypeKind.WILDCARD && types.isSubtype(et, iterable))) {
304                             al.addAll(varNamesForType(et, types, elements));
305                         } else {
306                             for (String JavaDoc name : varNamesForType(et, types, elements))
307                                 al.add(name.endsWith("s") ? name + "es" : name + "s"); //NOI18N
308
}
309                     }
310                 }
311                 if (sb.length() > 0)
312                     al.add(sb.toString());
313                 return al;
314             case WILDCARD:
315                 TypeMirror bound = ((WildcardType)type).getExtendsBound();
316                 if (bound == null)
317                     bound = ((WildcardType)type).getSuperBound();
318                 if (bound != null)
319                     return varNamesForType(bound, types, elements);
320         }
321         return Collections.<String JavaDoc>emptyList();
322     }
323     
324     private static String JavaDoc getConstName(String JavaDoc s) {
325         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
326         boolean prevUpper = false;
327         for (int i = 0; i < s.length(); i++) {
328             char c = s.charAt(i);
329             if (Character.isUpperCase(c)) {
330                 if (!prevUpper)
331                     sb.append('_');
332                 sb.append(c);
333                 prevUpper = true;
334             } else {
335                 sb.append(Character.toUpperCase(c));
336                 prevUpper = false;
337             }
338         }
339         return sb.toString();
340     }
341     
342     private static String JavaDoc nextName(CharSequence JavaDoc name) {
343         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
344         for (int i = 0; i < name.length(); i++) {
345             char c = name.charAt(i);
346             if (Character.isUpperCase(c)) {
347                 char lc = Character.toLowerCase(c);
348                 sb.append(lc);
349                 sb.append(name.subSequence(i + 1, name.length()));
350                 break;
351             }
352         }
353         return sb.toString();
354     }
355     
356     private static boolean isClashing(String JavaDoc varName, Iterable JavaDoc<? extends Element> locals) {
357         if (JavaTokenContext.getKeyword(varName) != null)
358             return true;
359         for (Element e : locals) {
360             if ((e.getKind() == ElementKind.LOCAL_VARIABLE || e.getKind() == ElementKind.PARAMETER || e.getKind() == ElementKind.EXCEPTION_PARAMETER) && varName.contentEquals(e.getSimpleName()))
361                 return true;
362         }
363         return false;
364     }
365     
366     private static class SettingsListener implements SettingsChangeListener {
367
368         public void settingsChange(SettingsChangeEvent evt) {
369             setCaseSensitive(SettingsUtil.getBoolean(JavaKit.class,
370                     ExtSettingsNames.COMPLETION_CASE_SENSITIVE,
371                     ExtSettingsDefaults.defaultCompletionCaseSensitive));
372         }
373     }
374
375     private static class TypeNameVisitor extends SimpleTypeVisitor6<StringBuilder JavaDoc,Boolean JavaDoc> {
376         
377         private boolean varArg;
378         
379         private TypeNameVisitor(boolean varArg) {
380             super(new StringBuilder JavaDoc());
381             this.varArg = varArg;
382         }
383         
384         @Override JavaDoc
385         public StringBuilder JavaDoc defaultAction(TypeMirror t, Boolean JavaDoc p) {
386             return DEFAULT_VALUE.append(t);
387         }
388         
389         @Override JavaDoc
390         public StringBuilder JavaDoc visitDeclared(DeclaredType t, Boolean JavaDoc p) {
391             Element e = t.asElement();
392             if (e instanceof TypeElement) {
393                 TypeElement te = (TypeElement)e;
394                 DEFAULT_VALUE.append((p ? te.getQualifiedName() : te.getSimpleName()).toString());
395                 Iterator<? extends TypeMirror> it = t.getTypeArguments().iterator();
396                 if (it.hasNext()) {
397                     DEFAULT_VALUE.append("<"); //NOI18N
398
while(it.hasNext()) {
399                         visit(it.next(), p);
400                         if (it.hasNext())
401                             DEFAULT_VALUE.append(", "); //NOI18N
402
}
403                     DEFAULT_VALUE.append(">"); //NOI18N
404
}
405                 return DEFAULT_VALUE;
406             } else {
407                 return DEFAULT_VALUE.append(UNKNOWN); //NOI18N
408
}
409         }
410                         
411         @Override JavaDoc
412         public StringBuilder JavaDoc visitArray(ArrayType t, Boolean JavaDoc p) {
413             boolean isVarArg = varArg;
414             varArg = false;
415             visit(t.getComponentType(), p);
416             return DEFAULT_VALUE.append(isVarArg ? "..." : "[]"); //NOI18N
417
}
418
419         @Override JavaDoc
420         public StringBuilder JavaDoc visitTypeVariable(TypeVariable t, Boolean JavaDoc p) {
421             Element e = t.asElement();
422             if (e != null) {
423                 String JavaDoc name = e.getSimpleName().toString();
424                 if (!CAPTURED_WILDCARD.equals(name))
425                     return DEFAULT_VALUE.append(name);
426             }
427             DEFAULT_VALUE.append("?"); //NOI18N
428
TypeMirror bound = t.getLowerBound();
429             if (bound != null && bound.getKind() != TypeKind.NULL) {
430                 DEFAULT_VALUE.append(" super "); //NOI18N
431
visit(bound, p);
432             } else {
433                 bound = t.getUpperBound();
434                 if (bound != null && bound.getKind() != TypeKind.NULL) {
435                     DEFAULT_VALUE.append(" extends "); //NOI18N
436
if (bound.getKind() == TypeKind.TYPEVAR)
437                         bound = ((TypeVariable)bound).getLowerBound();
438                     visit(bound, p);
439                 }
440             }
441             return DEFAULT_VALUE;
442         }
443
444         @Override JavaDoc
445         public StringBuilder JavaDoc visitWildcard(WildcardType t, Boolean JavaDoc p) {
446             DEFAULT_VALUE.append("?"); //NOI18N
447
TypeMirror bound = t.getSuperBound();
448             if (bound == null) {
449                 bound = t.getExtendsBound();
450                 if (bound != null) {
451                     DEFAULT_VALUE.append(" extends "); //NOI18N
452
if (bound.getKind() == TypeKind.WILDCARD)
453                         bound = ((WildcardType)bound).getSuperBound();
454                     visit(bound, p);
455                 }
456             } else {
457                 DEFAULT_VALUE.append(" super "); //NOI18N
458
visit(bound, p);
459             }
460             return DEFAULT_VALUE;
461         }
462
463         public StringBuilder JavaDoc visitError(ErrorType t, Boolean JavaDoc p) {
464             Element e = t.asElement();
465             if (e instanceof TypeElement) {
466                 TypeElement te = (TypeElement)e;
467                 return DEFAULT_VALUE.append((p ? te.getQualifiedName() : te.getSimpleName()).toString());
468             }
469             return DEFAULT_VALUE;
470         }
471     }
472     
473     private static class ElementNameVisitor extends SimpleElementVisitor6<StringBuilder JavaDoc,Boolean JavaDoc> {
474         
475         private ElementNameVisitor() {
476             super(new StringBuilder JavaDoc());
477         }
478
479         @Override JavaDoc
480         public StringBuilder JavaDoc visitPackage(PackageElement e, Boolean JavaDoc p) {
481             return DEFAULT_VALUE.append((p ? e.getQualifiedName() : e.getSimpleName()).toString());
482         }
483
484     @Override JavaDoc
485         public StringBuilder JavaDoc visitType(TypeElement e, Boolean JavaDoc p) {
486             return DEFAULT_VALUE.append((p ? e.getQualifiedName() : e.getSimpleName()).toString());
487         }
488     }
489 }
490
Popular Tags