0001: /*
0002: * Sun Public License Notice
0003: *
0004: * The contents of this file are subject to the Sun Public License
0005: * Version 1.0 (the "License"). You may not use this file except in
0006: * compliance with the License. A copy of the License is available at
0007: * http://www.sun.com/
0008: *
0009: * The Original Code is NetBeans. The Initial Developer of the Original
0010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
0011: * Microsystems, Inc. All Rights Reserved.
0012: */
0013:
0014: package org.netbeans.editor.ext.java;
0015:
0016: import java.lang.reflect.Modifier;
0017: import java.util.ArrayList;
0018: import java.util.HashMap;
0019: import java.util.Iterator;
0020: import java.util.List;
0021:
0022: import org.netbeans.editor.ext.Completion;
0023: import org.netbeans.editor.ext.CompletionQuery;
0024: import org.netbeans.editor.ext.CompletionView;
0025: import org.netbeans.editor.ext.ExtEditorUI;
0026: import org.netbeans.editor.ext.ListCompletionView;
0027:
0028: /**
0029: * Java completion query specifications
0030: *
0031: * @author Miloslav Metelka
0032: * @version 1.00
0033: */
0034:
0035: public class JavaCompletion extends Completion {
0036:
0037: public static final int PUBLIC_LEVEL = 3;
0038: public static final int PROTECTED_LEVEL = 2;
0039: public static final int PACKAGE_LEVEL = 1;
0040: public static final int PRIVATE_LEVEL = 0;
0041:
0042: public static final SimpleClass BOOLEAN_CLASS = new SimpleClass(
0043: "boolean", ""); // NOI18N
0044: public static final SimpleClass BYTE_CLASS = new SimpleClass(
0045: "byte", ""); // NOI18N
0046: public static final SimpleClass CHAR_CLASS = new SimpleClass(
0047: "char", ""); // NOI18N
0048: public static final SimpleClass DOUBLE_CLASS = new SimpleClass(
0049: "double", ""); // NOI18N
0050: public static final SimpleClass FLOAT_CLASS = new SimpleClass(
0051: "float", ""); // NOI18N
0052: public static final SimpleClass INT_CLASS = new SimpleClass("int",
0053: ""); // NOI18N
0054: public static final SimpleClass LONG_CLASS = new SimpleClass(
0055: "long", ""); // NOI18N
0056: public static final SimpleClass SHORT_CLASS = new SimpleClass(
0057: "short", ""); // NOI18N
0058: public static final SimpleClass VOID_CLASS = new SimpleClass(
0059: "void", ""); // NOI18N
0060:
0061: public static final BaseType BOOLEAN_TYPE = new BaseType(
0062: BOOLEAN_CLASS, 0);
0063: public static final BaseType BYTE_TYPE = new BaseType(BYTE_CLASS, 0);
0064: public static final BaseType CHAR_TYPE = new BaseType(CHAR_CLASS, 0);
0065: public static final BaseType DOUBLE_TYPE = new BaseType(
0066: DOUBLE_CLASS, 0);
0067: public static final BaseType FLOAT_TYPE = new BaseType(FLOAT_CLASS,
0068: 0);
0069: public static final BaseType INT_TYPE = new BaseType(INT_CLASS, 0);
0070: public static final BaseType LONG_TYPE = new BaseType(LONG_CLASS, 0);
0071: public static final BaseType SHORT_TYPE = new BaseType(SHORT_CLASS,
0072: 0);
0073: public static final BaseType VOID_TYPE = new BaseType(VOID_CLASS, 0);
0074:
0075: public static final SimpleClass INVALID_CLASS = new SimpleClass("",
0076: ""); // NOI18N
0077: public static final BaseType INVALID_TYPE = new BaseType(
0078: INVALID_CLASS, 0);
0079:
0080: public static final SimpleClass NULL_CLASS = new SimpleClass(
0081: "null", ""); // NOI18N
0082: public static final BaseType NULL_TYPE = new BaseType(NULL_CLASS, 0);
0083:
0084: public static final SimpleClass OBJECT_CLASS_ARRAY = new SimpleClass(
0085: "java.lang.Object[]", "java.lang".length(), true); // NOI18N
0086: public static final BaseType OBJECT_TYPE_ARRAY = new BaseType(
0087: OBJECT_CLASS_ARRAY, 0);
0088:
0089: public static final SimpleClass OBJECT_CLASS = new SimpleClass(
0090: "java.lang.Object", "java.lang".length(), true); // NOI18N
0091: public static final BaseType OBJECT_TYPE = new BaseType(
0092: OBJECT_CLASS, 0);
0093:
0094: public static final SimpleClass CLASS_CLASS = new SimpleClass(
0095: "java.lang.Class", "java.lang".length(), true); // NOI18N
0096: public static final BaseType CLASS_TYPE = new BaseType(CLASS_CLASS,
0097: 0);
0098:
0099: public static final SimpleClass STRING_CLASS = new SimpleClass(
0100: "java.lang.String", "java.lang".length(), true); // NOI18N
0101: public static final BaseType STRING_TYPE = new BaseType(
0102: STRING_CLASS, 0);
0103:
0104: static final int INTERFACE_BIT = (1 << 30); // no neg nums in modifiers
0105: static final int INTERFACE_BIT_FILTER = (~INTERFACE_BIT);
0106:
0107: private static final HashMap str2PrimitiveClass = new HashMap();
0108: private static final HashMap str2PrimitiveType = new HashMap();
0109:
0110: static {
0111: BaseType[] types = new BaseType[] { BOOLEAN_TYPE, BYTE_TYPE,
0112: CHAR_TYPE, DOUBLE_TYPE, FLOAT_TYPE, INT_TYPE,
0113: LONG_TYPE, SHORT_TYPE, VOID_TYPE };
0114:
0115: for (int i = types.length - 1; i >= 0; i--) {
0116: String typeName = types[i].getClazz().getName();
0117: str2PrimitiveClass.put(typeName, types[i].getClazz());
0118: str2PrimitiveType.put(typeName, types[i]);
0119: }
0120: }
0121:
0122: public static final JCParameter[] EMPTY_PARAMETERS = new JCParameter[0];
0123: public static final JCClass[] EMPTY_CLASSES = new JCClass[0];
0124: public static final JCPackage[] EMPTY_PACKAGES = new JCPackage[0];
0125: public static final JCField[] EMPTY_FIELDS = new JCField[0];
0126: public static final JCConstructor[] EMPTY_CONSTRUCTORS = new JCConstructor[0];
0127: public static final JCMethod[] EMPTY_METHODS = new JCMethod[0];
0128:
0129: private static JCFinder finder;
0130:
0131: private static int debugMode;
0132:
0133: /** Map holding the simple class instances */
0134: private static HashMap classCache = new HashMap(5003);
0135:
0136: /** Map holding the cached types */
0137: private static HashMap typeCache = new HashMap(5003);
0138:
0139: /** Debug expression creation */
0140: public static final int DEBUG_EXP = 1;
0141: /** Debug finding packages/classes/fields/methods */
0142: public static final int DEBUG_FIND = 2;
0143:
0144: /** Callback for initing completion. See EditorModule.restored(). */
0145: private static JCFinderInitializer initializer;
0146:
0147: /** Gets the current default finder. */
0148: public static synchronized JCFinder getFinder() {
0149: if (finder == null) {
0150: if (initializer == null) {
0151: throw new IllegalStateException(
0152: "Editor: Java completion can't be initialized.");
0153: }
0154:
0155: initializer.initJCFinder();
0156: }
0157:
0158: return finder;
0159: }
0160:
0161: /** Set the current default finder */
0162: public static synchronized void setFinder(JCFinder f) {
0163: finder = f;
0164: }
0165:
0166: /**
0167: * Sets initializer to init finder for case it's needed and was not done
0168: * yet.
0169: */
0170: public static void setFinderInitializer(
0171: JCFinderInitializer initializer) {
0172: JavaCompletion.initializer = initializer;
0173: }
0174:
0175: public JavaCompletion(ExtEditorUI extEditorUI) {
0176: super (extEditorUI);
0177: }
0178:
0179: protected CompletionView createView() {
0180: return new ListCompletionView(new JCCellRenderer());
0181: }
0182:
0183: protected CompletionQuery createQuery() {
0184: return new JavaCompletionQuery();
0185: }
0186:
0187: /** Get level from modifiers. */
0188: public static int getLevel(int modifiers) {
0189: if ((modifiers & Modifier.PUBLIC) != 0) {
0190: return PUBLIC_LEVEL;
0191: } else if ((modifiers & Modifier.PROTECTED) != 0) {
0192: return PROTECTED_LEVEL;
0193: } else if ((modifiers & Modifier.PRIVATE) == 0) {
0194: return PACKAGE_LEVEL;
0195: } else {
0196: return PRIVATE_LEVEL;
0197: }
0198: }
0199:
0200: public static boolean isPrimitiveClassName(String s) {
0201: return JavaTokenContext.isTypeOrVoid(s);
0202: }
0203:
0204: public static boolean isPrimitiveClass(JCClass c) {
0205: return (c.getPackageName().length() == 0)
0206: && isPrimitiveClassName(c.getName());
0207: }
0208:
0209: public static JCClass getPrimitiveClass(String s) {
0210: return (JCClass) str2PrimitiveClass.get(s);
0211: }
0212:
0213: public static JCType getPrimitiveType(String s) {
0214: return (JCType) str2PrimitiveType.get(s);
0215: }
0216:
0217: public static Iterator getPrimitiveClassIterator() {
0218: return str2PrimitiveClass.values().iterator();
0219: }
0220:
0221: public static JCClass getSimpleClass(String fullClassName,
0222: int packageNameLen) {
0223: JCClass cls = (JCClass) classCache.get(fullClassName);
0224: if (cls == null // not in cache yet
0225: || packageNameLen != cls.getPackageName().length() // different
0226: // class
0227: ) {
0228: cls = new SimpleClass(fullClassName, packageNameLen, true);
0229: classCache.put(fullClassName, cls);
0230: }
0231: return cls;
0232: }
0233:
0234: public static JCClass getSimpleClass(JCClass cls) {
0235: return getSimpleClass(cls.getFullName(), cls.getPackageName()
0236: .length());
0237: }
0238:
0239: public static JCClass createSimpleClass(String fullClassName) {
0240: int nameInd = fullClassName.lastIndexOf('.') + 1;
0241: return createSimpleClass(fullClassName.substring(nameInd),
0242: (nameInd > 0) ? fullClassName.substring(0, nameInd - 1)
0243: : ""); // NOI18N
0244: }
0245:
0246: public static JCClass createSimpleClass(String name,
0247: String packageName) {
0248: return new SimpleClass(name, packageName);
0249: }
0250:
0251: public static JCType createType(JCClass cls, int arrayDepth) {
0252: return new BaseType(cls, arrayDepth);
0253: }
0254:
0255: /**
0256: * Create new type or get the existing one from the cache. The cache holds
0257: * the arrays with the increasing array depth for the particular class as
0258: * the members. Simple class is used for the caching to make it independent
0259: * on the real completion classes that can become obsolete and thus should
0260: * be garbage collected.
0261: */
0262: public static JCType getType(JCClass cls, int arrayDepth) {
0263: if (cls == null) {
0264: return null;
0265: }
0266:
0267: JCType[] types = (JCType[]) typeCache.get(cls);
0268: if (types != null) {
0269: if (arrayDepth < types.length) {
0270: if (types[arrayDepth] == null) {
0271: types[arrayDepth] = new BaseType(types[0]
0272: .getClazz(), arrayDepth);
0273: }
0274: } else { // array length depth too small for given array depth
0275: cls = types[0].getClazz();
0276: JCType[] tmp = new JCType[arrayDepth + 1];
0277: System.arraycopy(types, 0, tmp, 0, types.length);
0278: types = tmp;
0279: types[arrayDepth] = new BaseType(cls, arrayDepth);
0280: typeCache.put(cls, types);
0281: }
0282: } else { // types array not yet created
0283: cls = getSimpleClass(cls.getFullName(), cls
0284: .getPackageName().length());
0285: if (arrayDepth > 0) {
0286: types = new JCType[arrayDepth + 1];
0287: types[arrayDepth] = new BaseType(cls, arrayDepth);
0288: } else {
0289: types = new JCType[2];
0290: }
0291: types[0] = new BaseType(cls, 0);
0292: typeCache.put(cls, types);
0293: }
0294:
0295: return types[arrayDepth];
0296: }
0297:
0298: public static class BasePackage implements JCPackage {
0299:
0300: private String name;
0301:
0302: private JCClass[] classes;
0303:
0304: private int dotCnt = -1;
0305:
0306: private String lastName;
0307:
0308: public BasePackage(String name) {
0309: this (name, EMPTY_CLASSES);
0310: }
0311:
0312: public BasePackage(String name, JCClass[] classes) {
0313: this .name = name;
0314: this .classes = classes;
0315: }
0316:
0317: /** Get full name of this package */
0318: public final String getName() {
0319: return name;
0320: }
0321:
0322: public String getLastName() {
0323: if (lastName == null) {
0324: lastName = name.substring(name.lastIndexOf('.') + 1);
0325: }
0326: return lastName;
0327: }
0328:
0329: /** Get classes contained in this package */
0330: public JCClass[] getClasses() {
0331: return classes;
0332: }
0333:
0334: public void setClasses(JCClass[] classes) {
0335: this .classes = classes;
0336: }
0337:
0338: public int getDotCount() {
0339: if (dotCnt < 0) {
0340: int i = 0;
0341: do {
0342: dotCnt++;
0343: i = name.indexOf('.', i) + 1;
0344: } while (i > 0);
0345: }
0346: return dotCnt;
0347: }
0348:
0349: public int compareTo(Object o) {
0350: if (this == o) {
0351: return 0;
0352: }
0353: JCPackage p = (JCPackage) o;
0354: return name.compareTo(p.getName());
0355: }
0356:
0357: public int hashCode() {
0358: return name.hashCode();
0359: }
0360:
0361: public boolean equals(Object o) {
0362: if (this == o) {
0363: return true;
0364: }
0365: if (o instanceof JCPackage) {
0366: return name.equals(((JCPackage) o).getName());
0367: }
0368: if (o instanceof String) {
0369: return name.equals((String) o);
0370: }
0371: return false;
0372: }
0373:
0374: public String toString() {
0375: return name;
0376: }
0377:
0378: }
0379:
0380: public static class SimpleClass implements JCClass {
0381:
0382: protected String name;
0383:
0384: protected String packageName;
0385:
0386: protected String fullName;
0387:
0388: public SimpleClass(String name, String packageName) {
0389: this .name = name;
0390: this .packageName = packageName;
0391: if (name == null || packageName == null) {
0392: throw new NullPointerException("className=" + name
0393: + ", packageName=" + packageName);
0394: }
0395: }
0396:
0397: public SimpleClass(String fullName, int packageNameLen,
0398: boolean intern) {
0399: this .fullName = fullName;
0400: if (packageNameLen <= 0) {
0401: name = fullName;
0402: packageName = ""; // NOI18N
0403: } else {
0404: // use interned strings here
0405: name = fullName.substring(packageNameLen + 1);
0406: packageName = fullName.substring(0, packageNameLen);
0407: if (intern) {
0408: name = name.intern();
0409: packageName = packageName.intern();
0410: }
0411: }
0412: }
0413:
0414: SimpleClass() {
0415: }
0416:
0417: public final String getName() {
0418: return name;
0419: }
0420:
0421: public final String getPackageName() {
0422: return packageName;
0423: }
0424:
0425: public String getFullName() {
0426: if (fullName == null) {
0427: fullName = (packageName.length() > 0) ? (packageName
0428: + "." + name) : name; // NOI18N
0429: }
0430: return fullName;
0431: }
0432:
0433: public int getTagOffset() {
0434: return -1;
0435: }
0436:
0437: public boolean isInterface() {
0438: return false;
0439: }
0440:
0441: public int getModifiers() {
0442: return 0;
0443: }
0444:
0445: public JCClass getSuperclass() {
0446: return null;
0447: }
0448:
0449: public JCClass[] getInterfaces() {
0450: return EMPTY_CLASSES;
0451: }
0452:
0453: public JCField[] getFields() {
0454: return EMPTY_FIELDS;
0455: }
0456:
0457: public JCConstructor[] getConstructors() {
0458: return EMPTY_CONSTRUCTORS;
0459: }
0460:
0461: public JCMethod[] getMethods() {
0462: return EMPTY_METHODS;
0463: }
0464:
0465: public int compareTo(Object o) {
0466: if (this == o) {
0467: return 0;
0468: }
0469: JCClass c = (JCClass) o;
0470:
0471: int order = packageName.compareTo(c.getPackageName());
0472: if (order == 0) {
0473: order = name.compareTo(c.getName());
0474: }
0475: return order;
0476: }
0477:
0478: public int hashCode() {
0479: return name.hashCode() ^ packageName.hashCode();
0480: }
0481:
0482: public boolean equals(Object o) {
0483: if (this == o) {
0484: return true;
0485: }
0486: if (o instanceof JCClass) {
0487: JCClass c = (JCClass) o;
0488: return name.equals(c.getName())
0489: && packageName.equals(c.getPackageName());
0490: }
0491: return false;
0492: }
0493:
0494: public String toString() {
0495: return (getPackageName().length() > 0) ? getPackageName()
0496: + '.' + getName().replace('.', '$') : getName()
0497: .replace('.', '$');
0498: }
0499:
0500: }
0501:
0502: /** Abstract class that assumes lazy initialization */
0503: public static abstract class AbstractClass extends SimpleClass {
0504:
0505: protected int modifiers;
0506:
0507: protected Body body;
0508:
0509: public AbstractClass(String name, String packageName,
0510: boolean iface, int modifiers) {
0511: super (name, packageName);
0512: this .modifiers = modifiers;
0513: if (iface) {
0514: this .modifiers |= INTERFACE_BIT;
0515: }
0516: }
0517:
0518: AbstractClass() {
0519: super ();
0520: }
0521:
0522: /** Init internal representation */
0523: protected abstract void init();
0524:
0525: /** Is this class an interface? */
0526: public boolean isInterface() {
0527: return ((modifiers & INTERFACE_BIT) != 0);
0528: }
0529:
0530: /** Get modifiers for this class */
0531: public int getModifiers() {
0532: return modifiers & INTERFACE_BIT_FILTER;
0533: }
0534:
0535: public int getTagOffset() {
0536: if (body == null) {
0537: init();
0538: }
0539: return body.tagOffset;
0540: }
0541:
0542: /** Get superclass of this class */
0543: public JCClass getSuperclass() {
0544: if (body == null) {
0545: init();
0546: }
0547: return body.super Class;
0548: }
0549:
0550: /** Get interfaces this class implements */
0551: public JCClass[] getInterfaces() {
0552: if (body == null) {
0553: init();
0554: }
0555: return body.interfaces;
0556: }
0557:
0558: /** Get fields that this class contains */
0559: public JCField[] getFields() {
0560: if (body == null) {
0561: init();
0562: }
0563: return body.fields;
0564: }
0565:
0566: /** Get constructors that this class contains */
0567: public JCConstructor[] getConstructors() {
0568: if (body == null) {
0569: init();
0570: }
0571: return body.constructors;
0572: }
0573:
0574: /** Get methods that this class contains */
0575: public JCMethod[] getMethods() {
0576: if (body == null) {
0577: init();
0578: }
0579: return body.methods;
0580: }
0581:
0582: public static class Body {
0583:
0584: public int tagOffset;
0585:
0586: public JCClass super Class;
0587:
0588: public JCClass[] interfaces;
0589:
0590: public JCField[] fields;
0591:
0592: public JCConstructor[] constructors;
0593:
0594: public JCMethod[] methods;
0595:
0596: }
0597:
0598: }
0599:
0600: /** Description of the type */
0601: public static class BaseType implements JCType {
0602:
0603: protected JCClass clazz;
0604:
0605: protected int arrayDepth;
0606:
0607: public BaseType(JCClass clazz, int arrayDepth) {
0608: this .clazz = clazz;
0609: this .arrayDepth = arrayDepth;
0610: if (arrayDepth < 0) {
0611: throw new IllegalArgumentException("Array depth "
0612: + arrayDepth + " < 0."); // NOI18N
0613: }
0614: }
0615:
0616: BaseType() {
0617: }
0618:
0619: public JCClass getClazz() {
0620: return clazz;
0621: }
0622:
0623: public int getArrayDepth() {
0624: return arrayDepth;
0625: }
0626:
0627: public String format(boolean useFullName) {
0628: StringBuffer sb = new StringBuffer(useFullName ? getClazz()
0629: .getFullName() : getClazz().getName());
0630: int ad = arrayDepth;
0631: while (ad > 0) {
0632: sb.append("[]"); // NOI18N
0633: ad--;
0634: }
0635: return sb.toString();
0636: }
0637:
0638: public int compareTo(Object o) {
0639: if (this == o) {
0640: return 0;
0641: }
0642: JCType t = (JCType) o;
0643: int order = clazz.compareTo(t.getClazz());
0644: if (order == 0) {
0645: order = arrayDepth - t.getArrayDepth();
0646: }
0647: return order;
0648: }
0649:
0650: public int hashCode() {
0651: return clazz.hashCode() + arrayDepth;
0652: }
0653:
0654: public boolean equals(Object o) {
0655: if (this == o) {
0656: return true;
0657: }
0658: if (o instanceof JCType) {
0659: JCType t = (JCType) o;
0660: return clazz.equals(t.getClazz())
0661: && arrayDepth == t.getArrayDepth();
0662: }
0663: return false;
0664: }
0665:
0666: public String toString() {
0667: StringBuffer sb = new StringBuffer(clazz.toString());
0668: int ad = arrayDepth;
0669: while (ad > 0) {
0670: sb.append("[]"); // NOI18N
0671: ad--;
0672: }
0673: return sb.toString();
0674: }
0675:
0676: }
0677:
0678: /** Description of the method parameter */
0679: public static class BaseParameter implements JCParameter {
0680:
0681: protected String name;
0682:
0683: protected JCType type;
0684:
0685: public BaseParameter(String name, JCType type) {
0686: this .name = name;
0687: this .type = type;
0688: }
0689:
0690: BaseParameter() {
0691: }
0692:
0693: /** Name of the parameter */
0694: public String getName() {
0695: return name;
0696: }
0697:
0698: /** Type of the parameter */
0699: public JCType getType() {
0700: return type;
0701: }
0702:
0703: public int compareTo(Object o) {
0704: if (this == o) {
0705: return 0;
0706: }
0707: JCParameter p = (JCParameter) o;
0708: return type.compareTo(p.getType()); // only by type
0709: }
0710:
0711: public int hashCode() {
0712: return type.hashCode() ^ name.hashCode();
0713: }
0714:
0715: public boolean equals(Object o) {
0716: if (this == o) {
0717: return true;
0718: }
0719: if (o instanceof JCParameter) {
0720: JCParameter p = (JCParameter) o;
0721: return type.equals(p.getType()); // only by type
0722: }
0723: return false;
0724: }
0725:
0726: public String toString() {
0727: return type.toString() + ' ' + name;
0728: }
0729:
0730: }
0731:
0732: public static class BaseField extends BaseParameter implements
0733: JCField {
0734:
0735: protected JCClass clazz;
0736:
0737: protected int modifiers;
0738:
0739: protected int tagOffset;
0740:
0741: public BaseField(JCClass clazz, String name, JCType type,
0742: int modifiers) {
0743: super (name, type);
0744: this .clazz = clazz;
0745: this .modifiers = modifiers;
0746: }
0747:
0748: BaseField() {
0749: }
0750:
0751: public int getModifiers() {
0752: return modifiers;
0753: }
0754:
0755: public JCClass getClazz() {
0756: return clazz;
0757: }
0758:
0759: public int getTagOffset() {
0760: return tagOffset;
0761: }
0762:
0763: public int compareTo(Object o) {
0764: if (this == o) {
0765: return 0;
0766: }
0767: JCField f = (JCField) o;
0768: int order = super .compareTo(o);
0769: if (order == 0) {
0770: order = name.compareTo(f.getName());
0771: }
0772: return order;
0773: }
0774:
0775: public int hashCode() {
0776: return type.hashCode() ^ name.hashCode() ^ modifiers;
0777: }
0778:
0779: public boolean equals(Object o) {
0780: if (this == o) {
0781: return true;
0782: }
0783: if (o instanceof JCField) {
0784: JCField p = (JCField) o;
0785: return name.equals(p.getName())
0786: && type.equals(p.getType());
0787: }
0788: return false;
0789: }
0790:
0791: public String toString() {
0792: return Modifier.toString(modifiers) + ' '
0793: + super .toString();
0794: }
0795:
0796: }
0797:
0798: public static class BaseConstructor implements JCConstructor {
0799:
0800: protected JCClass clazz;
0801:
0802: protected int tagOffset;
0803:
0804: protected int modifiers;
0805:
0806: protected JCParameter[] parameters;
0807:
0808: protected JCClass[] exceptions;
0809:
0810: public BaseConstructor(JCClass clazz, int modifiers,
0811: JCParameter[] parameters, JCClass[] exceptions) {
0812: this .clazz = clazz;
0813: this .modifiers = modifiers;
0814: this .parameters = parameters;
0815: this .exceptions = exceptions;
0816: }
0817:
0818: BaseConstructor() {
0819: }
0820:
0821: public JCClass getClazz() {
0822: return clazz;
0823: }
0824:
0825: public int getTagOffset() {
0826: return tagOffset;
0827: }
0828:
0829: public int getModifiers() {
0830: return modifiers;
0831: }
0832:
0833: public JCParameter[] getParameters() {
0834: return parameters;
0835: }
0836:
0837: public JCClass[] getExceptions() {
0838: return exceptions;
0839: }
0840:
0841: /**
0842: * This implementation expects that only the constructors inside one
0843: * class will be compared.
0844: */
0845: public int compareTo(Object o) {
0846: if (this == o) {
0847: return 0;
0848: }
0849: JCConstructor c = (JCConstructor) o;
0850: int order = 0;
0851: JCParameter[] mp = c.getParameters();
0852: int commonCnt = Math.min(parameters.length, mp.length);
0853: for (int i = 0; i < commonCnt; i++) {
0854: order = parameters[i].compareTo(mp[i]);
0855: if (order != 0) {
0856: return order;
0857: }
0858: }
0859: order = parameters.length - mp.length;
0860: return order;
0861: }
0862:
0863: public boolean equals(Object o) {
0864: if (this == o) {
0865: return true;
0866: }
0867: if (o instanceof JCConstructor) {
0868: return (compareTo(o) == 0);
0869: }
0870: return false;
0871: }
0872:
0873: public int hashCode() {
0874: int h = 0;
0875: for (int i = 0; i < parameters.length; i++) {
0876: h ^= parameters[i].hashCode();
0877: }
0878: return h;
0879: }
0880:
0881: String toString(String returnTypeName, String methodName) {
0882: StringBuffer sb = new StringBuffer(Modifier
0883: .toString(modifiers));
0884: sb.append(' ');
0885: sb.append(returnTypeName);
0886: sb.append(methodName);
0887: // Add parameters
0888: sb.append('(');
0889: int cntM1 = parameters.length - 1;
0890: for (int i = 0; i <= cntM1; i++) {
0891: sb.append(parameters[i].toString());
0892: if (i < cntM1) {
0893: sb.append(", "); // NOI18N
0894: }
0895: }
0896: sb.append(')');
0897: // Add exceptions
0898: cntM1 = exceptions.length - 1;
0899: if (cntM1 >= 0) {
0900: sb.append(" throws "); // NOI18N
0901: for (int i = 0; i <= cntM1; i++) {
0902: sb.append(exceptions[i].toString());
0903: if (i < cntM1) {
0904: sb.append(", "); // NOI18N
0905: }
0906: }
0907: }
0908: return sb.toString();
0909: }
0910:
0911: public String toString() {
0912: return toString("", getClazz().getName()); // NOI18N
0913: }
0914:
0915: }
0916:
0917: public static class BaseMethod extends BaseConstructor implements
0918: JCMethod {
0919:
0920: protected String name;
0921:
0922: protected JCType returnType;
0923:
0924: public BaseMethod(JCClass clazz, String name, int modifiers,
0925: JCType returnType, JCParameter[] parameters,
0926: JCClass[] exceptions) {
0927: super (clazz, modifiers, parameters, exceptions);
0928: this .name = name;
0929: this .returnType = returnType;
0930: }
0931:
0932: BaseMethod() {
0933: }
0934:
0935: public String getName() {
0936: return name;
0937: }
0938:
0939: public JCType getReturnType() {
0940: return returnType;
0941: }
0942:
0943: public int compareTo(Object o) {
0944: if (this == o) {
0945: return 0;
0946: }
0947: JCMethod m = (JCMethod) o;
0948: int order = name.compareTo(m.getName());
0949: if (order == 0) {
0950: order = super .compareTo(o);
0951: }
0952: return order;
0953: }
0954:
0955: public int hashCode() {
0956: return name.hashCode() ^ super .hashCode();
0957: }
0958:
0959: public boolean equals(Object o) {
0960: if (this == o) {
0961: return true;
0962: }
0963: if (o instanceof JCMethod) {
0964: return (compareTo(o) == 0);
0965: }
0966: return false;
0967: }
0968:
0969: public String toString() {
0970: String rtn = getReturnType().toString();
0971: return toString((rtn.length() > 0) ? rtn + ' ' : "", name); // NOI18N
0972: }
0973:
0974: }
0975:
0976: public abstract static class AbstractProvider implements
0977: JCClassProvider {
0978:
0979: public abstract Iterator getClasses();
0980:
0981: public boolean append(JCClassProvider cp) {
0982: Iterator i = cp.getClasses();
0983: while (i.hasNext()) {
0984: JCClass c = (JCClass) i.next();
0985: if (!cp.notifyAppend(c, false)) {
0986: return false;
0987: }
0988: if (!appendClass(c)) {
0989: return false;
0990: }
0991: if (!cp.notifyAppend(c, true)) {
0992: return false;
0993: }
0994: }
0995: return true;
0996: }
0997:
0998: protected boolean appendClass(JCClass c) {
0999: return true;
1000: }
1001:
1002: public void reset() {
1003: }
1004:
1005: /**
1006: * This method is executed by the target Class Provider to notify this
1007: * provider about the class appending.
1008: *
1009: * @param c
1010: * JC class that was appended
1011: * @return true to continue building, false to stop build
1012: */
1013: public boolean notifyAppend(JCClass c, boolean appendFinished) {
1014: return true;
1015: }
1016:
1017: }
1018:
1019: public static class ListProvider extends AbstractProvider {
1020:
1021: private List classList;
1022:
1023: public ListProvider() {
1024: classList = new ArrayList();
1025: }
1026:
1027: public ListProvider(List classList) {
1028: this .classList = classList;
1029: }
1030:
1031: protected boolean appendClass(JCClass c) {
1032: classList.add(c);
1033: return true;
1034: }
1035:
1036: public Iterator getClasses() {
1037: return classList.iterator();
1038: }
1039:
1040: public int getClassCount() {
1041: return classList.size();
1042: }
1043:
1044: }
1045:
1046: public static class SingleProvider extends AbstractProvider
1047: implements Iterator {
1048:
1049: JCClass c;
1050:
1051: boolean next = true;
1052:
1053: public SingleProvider(JCClass c) {
1054: this .c = c;
1055: }
1056:
1057: public Iterator getClasses() {
1058: if (next) {
1059: return this ;
1060: } else {
1061: throw new IllegalStateException();
1062: }
1063: }
1064:
1065: public boolean hasNext() {
1066: return next;
1067: }
1068:
1069: public Object next() {
1070: next = false;
1071: return c;
1072: }
1073:
1074: public void remove() {
1075: throw new UnsupportedOperationException();
1076: }
1077:
1078: }
1079:
1080: public static int getDebugMode() {
1081: return debugMode;
1082: }
1083:
1084: public static void setDebugMode(int newDebugMode) {
1085: debugMode = newDebugMode;
1086: }
1087:
1088: /** Interface for providing callback initialization of JavaCompletion. */
1089: public static interface JCFinderInitializer {
1090: public void initJCFinder();
1091: }
1092: }
|