001: package tide.classsyntax;
002:
003: import tide.sources.*;
004: import tide.project.*;
005: import tide.editor.*;
006: import java.util.*;
007: import java.lang.reflect.*;
008: import tide.editor.completions.*;
009: import tide.syntaxtree.*;
010:
011: /** Used for the completion. Uses reflection.
012: * Other possibilities (TODO):
013: * 1) use javaCC trees, cached or update them
014: * 2) use bcel,
015: * present in jdk1.5.0_07+ ??
016: * com.sun.org.apache.bcel.internal.classfile NO NO NO, not supported, use ASM, much better !
017: *
018: * TODO: import javax only shows the first hits if such a package is found in the project.
019: * and only in the first jar if found => collect in project and all libs...
020: */
021: public final class ClassSyntaxManager {
022:
023: /*
024: CAUTION: getDeclaredClasses, Methods and Fields gives all including private and protected.
025: getClasses, Meth and Fields gives also from the superclass but ONLY public
026: => one must iterate over the superclasses and use getDeclared...
027: */
028:
029: // Remarks: synthetic ??
030: // java.lang.annotation.ElementType: unknown source, loader=null
031: // Synthetic public int java.lang.Enum.compareTo(java.lang.Object)
032: private ClassSyntaxManager() {
033: }
034:
035: /** Fields and methods and (recursively) static class members
036: * + enums (always !)
037: */
038: private static List<AttrCompletionItem> getClassAttributes(Class c,
039: String typeParameters, boolean includePrivate,
040: boolean includeProtected, boolean includePackageScope,
041: boolean staticOnly, final StringBuilder paramsMapperText) {
042: List<AttrCompletionItem> attrs = new ArrayList<AttrCompletionItem>();
043:
044: // Methods
045: //
046:
047: ArrayList<Method> methods = new ArrayList<Method>();
048: ArrayList<Boolean> inherited = new ArrayList<Boolean>();
049:
050: try {
051: for (Method m : c.getDeclaredMethods()) // also private but only from the class, not superclasses
052: {
053: if (m.getName().startsWith("access$"))
054: continue; // what are these ones ??
055:
056: methods.add(m);
057: inherited.add(false);
058: }
059: } catch (Exception e) {
060: e.printStackTrace();
061: } // illegal access ??
062: catch (Error e) {
063: e.printStackTrace();
064: } // illegal access ??
065:
066: try {
067: for (Method m : c.getMethods()) // public
068: {
069: if (!methods.contains(m)) {
070: if (m.getName().startsWith("access$"))
071: continue; // what are these ones ??
072:
073: methods.add(m);
074: inherited.add(true);
075: }
076: }
077: } catch (Exception e) {
078: e.printStackTrace();
079: } // illegal access ??
080: catch (Error e) {
081: e.printStackTrace();
082: } // illegal access ??
083:
084: try {
085: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
086: Class sc = c;
087: while ((sc = sc.getSuperclass()) != null) {
088: for (Method m : sc.getDeclaredMethods()) {
089: if (!Modifier.isPrivate(m.getModifiers()) // only protected make sense
090: && !methods.contains(m)) {
091: methods.add(m);
092: inherited.add(true);
093: }
094: }
095: }
096: } catch (Exception e) {
097: e.printStackTrace();
098: } catch (Error e) {
099: e.printStackTrace();
100: }
101:
102: // TODO: (??) look if need to map differently superclasses type params...
103: TypeParametersMapper mapper = new TypeParametersMapper(c
104: .getTypeParameters(), typeParameters);
105: if (paramsMapperText != null) {
106: paramsMapperText.append(mapper.toString());
107: }
108:
109: try {
110: for (int i = 0; i < methods.size(); i++) {
111: Method m = methods.get(i);
112: if (m.getName().startsWith("access$"))
113: continue;
114:
115: boolean stat = Modifier.isStatic(m.getModifiers());
116: if (staticOnly && !stat)
117: continue;
118: if (!includePrivate
119: && Modifier.isPrivate(m.getModifiers()))
120: continue;
121: if (!includeProtected
122: && Modifier.isProtected(m.getModifiers()))
123: continue;
124: if (!includePackageScope
125: && !ClassUtils.isAtLeastPackageScope(m
126: .getModifiers()))
127: continue;
128:
129: AttrCompletionItem ai = AttrCompletionItem
130: .createNameCompletion(m, ("M " + ClassUtils
131: .toStringPrincipalModifiersShort(m
132: .getModifiers())).trim(),
133: inherited.get(i), mapper);
134: attrs.add(ai);
135:
136: }
137: } catch (Exception e) {
138: e.printStackTrace();
139: } catch (Error e) {
140: e.printStackTrace();
141: }
142:
143: // inner classes (recurse !)
144: //
145:
146: ArrayList<Class> classes = new ArrayList<Class>();
147: inherited.clear();
148: try {
149:
150: /*
151: tide> Exception in thread "AttributesCompletion:names" java.lang.IllegalAccessError:
152: tried to access class snow.SortableTable.UniversalTableEditor$FontCellEditor from class snow.sortabletable.UniversalTableEditor
153: */
154: for (Class cl : c.getDeclaredClasses()) {
155: classes.add(cl);
156: inherited.add(false);
157: }
158: } catch (Exception e) {
159: e.printStackTrace();
160: } catch (Error e) {
161: e.printStackTrace();
162: }
163:
164: try {
165: for (Class ci : c.getClasses()) {
166: if (!classes.contains(ci)) {
167: classes.add(ci);
168: inherited.add(true);
169: }
170: }
171: } catch (Exception e) {
172: e.printStackTrace();
173: } // illegal access ??
174: catch (Error e) {
175: e.printStackTrace();
176: } // illegal access ??
177:
178: //[April2007]: look in superclasses
179: try {
180: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
181: Class sc = c;
182: while ((sc = sc.getSuperclass()) != null) {
183: for (Class ci : sc.getDeclaredClasses()) {
184: if (!classes.contains(ci)) {
185: classes.add(ci);
186: inherited.add(true);
187: }
188: }
189: }
190: } catch (Exception e) {
191: e.printStackTrace();
192: } // illegal access ??
193: catch (Error e) {
194: e.printStackTrace();
195: } // illegal access ??
196:
197: classes.remove(c); // just for security
198:
199: for (Class cl : classes) // For example Point2D.Double
200: {
201: //boolean stat = ;
202: //NO, alwasy show if(Modifier.isStatic(cl.getModifiers()))
203: //[April2007]: inner classes are visible even if not static, as DecClass.TMember
204: {
205: String prefix = "";
206: if (cl.isEnum()) {
207: prefix = "enum pub sta";
208: } else if (cl.isAnnotation()) {
209: prefix = "annotation";
210: } else {
211: // internal static class
212: prefix = ("ISCL " + ClassUtils
213: .toStringPrincipalModifiersShort(cl
214: .getModifiers())).trim();
215: }
216:
217: AttrCompletionItem ai = AttrCompletionItem
218: .createInternalClassCompletion(cl, prefix,
219: false);
220: attrs.add(ai);
221: }
222: }
223:
224: // fields
225: //
226:
227: ArrayList<Field> fields = new ArrayList<Field>();
228: inherited.clear();
229: try {
230: for (Field fi : c.getDeclaredFields()) {
231: fields.add(fi);
232: inherited.add(false);
233: }
234:
235: for (Field fi : c.getFields()) {
236: if (!fields.contains(fi)) {
237: fields.add(fi);
238: inherited.add(true);
239: }
240: }
241:
242: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
243: Class sc = c;
244: while ((sc = sc.getSuperclass()) != null) {
245: for (Field fi : sc.getDeclaredFields()) {
246: if (!fields.contains(fi)) {
247: fields.add(fi);
248: inherited.add(true);
249: }
250: }
251: }
252: } catch (Exception e) {
253: e.printStackTrace();
254: } // illegal access ??
255: catch (Error e) {
256: e.printStackTrace();
257: } // illegal access ??
258:
259: for (int i = 0; i < fields.size(); i++) {
260: Field f = fields.get(i);
261:
262: boolean stat = Modifier.isStatic(f.getModifiers());
263: if (staticOnly && !stat)
264: continue;
265: if (!includePrivate && Modifier.isPrivate(f.getModifiers()))
266: continue;
267: if (!includeProtected
268: && Modifier.isProtected(f.getModifiers()))
269: continue;
270: if (!includePackageScope
271: && !ClassUtils.isAtLeastPackageScope(f
272: .getModifiers()))
273: continue;
274:
275: AttrCompletionItem ai = AttrCompletionItem
276: .createNameCompletion(f, ("F " + ClassUtils
277: .toStringPrincipalModifiersShort(f
278: .getModifiers())).trim(), inherited
279: .get(i), mapper);
280: attrs.add(ai);
281: }
282:
283: return attrs;
284: }
285:
286: /** @return the Arguments completions items for all the methods named methodName.
287: */
288: public static List<AttrCompletionItem> getMethodsArgs(
289: SingleClassLoader scl, String javaClassName,
290: String methodName, String classParameters,
291: boolean includePrivate, boolean includeProtected,
292: boolean includePackageScope, boolean staticOnly) {
293: List<AttrCompletionItem> attrs = new ArrayList<AttrCompletionItem>();
294: try {
295: Class c = scl.findClass(javaClassName);
296: //System.out.println("found class: "+c);
297: if (c != null) {
298:
299: ArrayList<Method> methods = new ArrayList<Method>();
300: ArrayList<Boolean> inherited = new ArrayList<Boolean>(); // collection sync with methods...
301:
302: for (Method m : c.getDeclaredMethods()) // also protected and private, but ONLY for this type, not supertyes !!!
303: {
304: if (m.getName().equals(methodName)) {
305: methods.add(m);
306: inherited.add(false);
307: }
308: }
309:
310: for (Method m : c.getMethods()) {
311: if (!methods.contains(m)
312: && m.getName().equals(methodName)) {
313: methods.add(m);
314: inherited.add(true);
315: }
316: }
317:
318: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
319: Class sc = c;
320: while ((sc = sc.getSuperclass()) != null) {
321: for (Method m : sc.getDeclaredMethods()) {
322: if (!Modifier.isPrivate(m.getModifiers()) // only protected
323: && !methods.contains(m)
324: && m.getName().equals(methodName)) {
325: methods.add(m);
326: inherited.add(true);
327: }
328: }
329: }
330:
331: TypeVariable[] tvs = c.getTypeParameters();
332: //System.out.println("Type variables = "+Arrays.toString(tvs));
333: TypeParametersMapper mapper = new TypeParametersMapper(
334: tvs, classParameters);
335:
336: for (int i = 0; i < methods.size(); i++) {
337: Method m = methods.get(i);
338:
339: boolean stat = Modifier.isStatic(m.getModifiers());
340: if (staticOnly && !stat)
341: continue;
342: if (!includePrivate
343: && Modifier.isPrivate(m.getModifiers()))
344: continue;
345: if (!includeProtected
346: && Modifier.isProtected(m.getModifiers()))
347: continue;
348: if (!includePackageScope
349: && !ClassUtils.isAtLeastPackageScope(m
350: .getModifiers()))
351: continue;
352:
353: AttrCompletionItem ai = AttrCompletionItem
354: .createArgumentsCompletion(
355: m,
356: ("M " + ClassUtils
357: .toStringPrincipalModifiersShort(m
358: .getModifiers()))
359: .trim(), inherited.get(i),
360: mapper);
361: attrs.add(ai);
362: }
363:
364: }
365: } catch (Exception e) {
366: e.printStackTrace();
367: }
368:
369: return attrs;
370: }
371:
372: /** Collects methods and fields.
373: * here we can be clever (TODO !), look in class instead of parsing, if the class is uptodate (look at dates)
374: * not included: names "access$*"
375: */
376: public static List<AttrCompletionItem> getAttributes(
377: SingleClassLoader scl, String javaName,
378: String typeParameters, boolean includePrivate,
379: boolean includeProtected, boolean includePackageScope,
380: boolean staticOnly) {
381: List<AttrCompletionItem> attrs = new ArrayList<AttrCompletionItem>();
382:
383: // try to parse bytecode (QUICK & Powerful & EXACT !), but requires the class to be compiled and uptodate !
384: ClassFilesManager cfm = MainEditorFrame.instance
385: .getActualProject().getClassFilesManager();
386: try {
387: Class c = scl.findClass(javaName);
388: //System.out.println("found class: "+c);
389: if (c != null) {
390: // c.getMethods()
391: // causes an Exception in thread "AttributesCompletion:names" java.lang.VerifyError: (class: javax/swing/JTable, method: processKeyBinding signature: (Ljavax/swing/KeyStroke;Ljava/awt/event/KeyEvent;IZ)Z) Bad access to protected data
392: // when a part is loaded with 1.6 (java.*) and a part with 1.5 (javax.*)
393: //
394: // or:
395: // Exception in thread "AttributesCompletion:names" java.lang.LinkageError: loader constraints violated when linking java/lang/String class
396:
397: attrs.addAll(getClassAttributes(c, typeParameters,
398: includePrivate, includeProtected,
399: includePackageScope, staticOnly, null)); // TODO.
400:
401: Class sc = c.getSuperclass();
402: if (sc != null) {
403: attrs.add(AttrCompletionItem.super MemberItem(sc
404: .getName()));
405: }
406: }
407: } catch (Exception e) {
408: e.printStackTrace();
409: }
410:
411: if (staticOnly) {
412: attrs.add(AttrCompletionItem.classMemberItem(javaName));
413: }
414:
415: // always... but makes only sense in a blok to access enclosing class instance ref
416: attrs.add(AttrCompletionItem.this MemberItem(javaName));
417:
418: return attrs;
419: }
420:
421: /** Collect constructors. WHEN DOT PRESSED
422: * here we can be clever (TODO !), look in class instead of parsing, if the class is
423: * uptodate (look at dates)
424: */
425: public static List<AttrCompletionItem> getCompletionForConstructors(
426: SingleClassLoader scl, String javaName,
427: String typeParameters, boolean includePrivate,
428: boolean includeProtected, boolean includePackageScope,
429: boolean staticOnly) {
430: List<AttrCompletionItem> attrs = new ArrayList<AttrCompletionItem>();
431:
432: boolean parseBytecode = true;
433:
434: if (parseBytecode) {
435: // try to parse bytecode (QUICK & Powerful & EXACT !), but requires the class to be compiled and uptodate !
436: //ClassFilesManager cfm = MainEditorFrame.instance.getActualProject().getClassFilesManager();
437: //SingleClassLoader scl = new SingleClassLoader(cfm);
438: Class c = scl.findClass(javaName);
439: if (c != null) {
440: TypeParametersMapper mapper = new TypeParametersMapper(
441: c.getTypeParameters(), typeParameters);
442: ArrayList<Constructor> constr = new ArrayList<Constructor>();
443: ArrayList<Boolean> inherited = new ArrayList<Boolean>();
444:
445: try {
446: for (Constructor ci : c.getDeclaredConstructors()) {
447: constr.add(ci);
448: inherited.add(false);
449: }
450: } catch (Exception e) {
451: e.printStackTrace();
452: } catch (Error e) {
453: e.printStackTrace();
454: }
455:
456: try {
457: for (Constructor fi : c.getConstructors()) {
458: if (!constr.contains(fi)) {
459: constr.add(fi);
460: inherited.add(true);
461: }
462: }
463: } catch (Exception e) {
464: e.printStackTrace();
465: } catch (Error e) {
466: e.printStackTrace();
467: }
468:
469: try {
470: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
471: Class sc = c;
472: while ((sc = sc.getSuperclass()) != null) {
473: for (Constructor m : sc
474: .getDeclaredConstructors()) {
475: if (!Modifier.isPrivate(m.getModifiers()) // only protected
476: && !constr.contains(m)) {
477: constr.add(m);
478: inherited.add(true);
479: }
480: }
481: }
482: } catch (Exception e) {
483: e.printStackTrace();
484: } catch (Error e) {
485: e.printStackTrace();
486: }
487:
488: int i = 0;
489: for (Constructor co : constr) {
490: if (!includePrivate
491: && Modifier.isPrivate(co.getModifiers()))
492: continue;
493: if (!includeProtected
494: && Modifier.isProtected(co.getModifiers()))
495: continue;
496: if (!includePackageScope
497: && !ClassUtils.isAtLeastPackageScope(co
498: .getModifiers()))
499: continue;
500:
501: AttrCompletionItem ai = AttrCompletionItem
502: .createNameCompletion(
503: co,
504: ("Co " + ClassUtils
505: .toStringPrincipalModifiersShort(co
506: .getModifiers()))
507: .trim(), inherited.get(i),
508: mapper);
509: //ai.setMember(co);
510: attrs.add(ai);
511: i++;
512: }
513:
514: // static classes
515: ArrayList<Class> classes = new ArrayList<Class>();
516: inherited.clear();
517:
518: for (Class ci : c.getDeclaredClasses()) {
519: classes.add(ci);
520: inherited.add(false);
521: }
522:
523: for (Class ci : c.getClasses()) {
524: if (!classes.contains(ci)) {
525: classes.add(ci);
526: inherited.add(true);
527: }
528:
529: }
530: i = 0;
531: for (Class cl : classes) // For example Point2D.Double
532: {
533: //boolean stat = Modifier.isStatic(cl.getModifiers());
534: // todo: look at their constructors !
535:
536: AttrCompletionItem ai = AttrCompletionItem
537: .createNameCompletion(
538: cl,
539: ("IC " + ClassUtils
540: .toStringPrincipalModifiersShort(cl
541: .getModifiers()))
542: .trim(), inherited.get(i));
543: i++;
544:
545: attrs.add(ai);
546: }
547: }
548: } // end if(parseBytecode)
549:
550: return attrs;
551: }
552:
553: /** All the constructors of the given class.
554: * @param paramsMapperText if non null, will be filled with the mapping of the class parameters, as for example "E=String, K=Vector<String>".
555: */
556: public static List<AttrCompletionItem> getConstructorsArgs(
557: SingleClassLoader scl, String javaName,
558: String typeParameters, boolean includePrivate,
559: boolean includeProtected, boolean includePackageScope,
560: boolean staticOnly, final StringBuilder paramsMapperText) {
561: List<AttrCompletionItem> attrs = new ArrayList<AttrCompletionItem>();
562:
563: Class c = scl.findClass(javaName);
564: if (c != null) {
565: TypeParametersMapper mapper = new TypeParametersMapper(c
566: .getTypeParameters(), typeParameters);
567: if (paramsMapperText != null) {
568: paramsMapperText.append(mapper.toString());
569: }
570:
571: ArrayList<Constructor> constr = new ArrayList<Constructor>();
572: ArrayList<Boolean> inherited = new ArrayList<Boolean>();
573: try {
574: for (Constructor ci : c.getDeclaredConstructors()) {
575: constr.add(ci);
576: inherited.add(false);
577: }
578: } catch (Exception e) {
579: e.printStackTrace();
580: } catch (Error e) {
581: e.printStackTrace();
582: }
583:
584: try {
585: for (Constructor fi : c.getConstructors()) {
586: if (!constr.contains(fi)) {
587: constr.add(fi);
588: inherited.add(true);
589: }
590: }
591: } catch (Exception e) {
592: e.printStackTrace();
593: } catch (Error e) {
594: e.printStackTrace();
595: }
596:
597: try {
598: // [April2007]: also look for protected super ones (private are not accessible and public are already present) !
599: Class sc = c;
600: while ((sc = sc.getSuperclass()) != null) {
601: for (Constructor m : sc.getDeclaredConstructors()) {
602: if (Modifier.isProtected(m.getModifiers()) // only protected
603: && !constr.contains(m)) {
604: constr.add(m);
605: inherited.add(true);
606: }
607: }
608: }
609: } catch (Exception e) {
610: e.printStackTrace();
611: } catch (Error e) {
612: e.printStackTrace();
613: }
614:
615: int i = 0;
616: for (Constructor co : constr) {
617: if (!includePrivate
618: && Modifier.isPrivate(co.getModifiers()))
619: continue;
620: if (!includeProtected
621: && Modifier.isProtected(co.getModifiers()))
622: continue;
623: if (!includePackageScope
624: && !ClassUtils.isAtLeastPackageScope(co
625: .getModifiers()))
626: continue;
627:
628: AttrCompletionItem ai = AttrCompletionItem
629: .createArgumentsCompletion(
630: co,
631: ("C " + ClassUtils
632: .toStringPrincipalModifiersShort(co
633: .getModifiers()))
634: .trim(), inherited.get(i),
635: mapper);
636: attrs.add(ai);
637: i++;
638: }
639: } else {
640: System.out.println("construct search: class not found: "
641: + javaName);
642: }
643:
644: return attrs;
645: }
646: /*
647: public static void main(String[] arguments)
648: {
649: Class c = "".getClass();
650: Constructor co = c.getConstructors()[0];
651: System.out.println(""+co);
652: System.out.println(""+Arrays.toString(co.getParameterTypes()));
653: //System.out.println(""+co.getSignature());
654: System.out.println(""+co.toGenericString());
655: }*/
656:
657: }
|