001: package tide.editor.completions;
002:
003: import snow.utils.StringUtils;
004: import tide.utils.SyntaxUtils;
005: import tide.project.JDocRes;
006: import java.lang.reflect.*;
007: import tide.classsyntax.ElementKind;
008: import tide.classsyntax.ClassUtils;
009: import tide.classsyntax.TypeParametersMapper;
010: import tide.sources.FileItem;
011:
012: /** An item appearing in a completion dialog. Used for fields, methods, constructors, and arguments...
013: * Note: their creation should be quick. One can delay some detailled informations
014: * as the parameter names in a background task.
015: */
016: public final class AttrCompletionItem {
017: public JDocRes jdoc = null;
018: // not used now.
019: private ElementKind kind = ElementKind.Unknown;
020:
021: final private String completion, returnType;
022: private String nameAndParams;
023: final public String kindAndModifiers;
024: final public boolean deprecated;
025:
026: // used for help, javadoc location, ... Class, Method, Field, ...
027: private Object member;
028:
029: public Class declaringClass;
030: private boolean inherited = false;
031:
032: public boolean selectedInView = false;
033: public final String customJavaDoc;
034:
035: /** number of chars to rewind (0=> do nothing)
036: */
037: public int rewindCaret = 0;
038:
039: // cached here because needed later when eventually injecting names
040: TypeParametersMapper mapper = null;
041:
042: /** instancied through the factories "create*"
043: */
044: private AttrCompletionItem(ElementKind kind,
045: String kindAndModifiers, String completion,
046: String nameAndParams, String returnType, boolean deprecated) {
047: this (kind, kindAndModifiers, completion, nameAndParams,
048: returnType, deprecated, null);
049: }
050:
051: /** instancied through the factories "create*"
052: */
053: private AttrCompletionItem(ElementKind kind,
054: String kindAndModifiers, String completion,
055: String nameAndParams, String returnType,
056: boolean deprecated, String customJavaDoc) {
057: this .kind = kind;
058: this .kindAndModifiers = kindAndModifiers;
059: this .completion = completion;
060: this .nameAndParams = nameAndParams;
061: this .returnType = returnType;
062:
063: // this.member = member;
064: this .deprecated = deprecated;
065: // this.inherited = inherited;
066:
067: this .customJavaDoc = customJavaDoc;
068: }
069:
070: //
071: // Name comletions are used when "." is pressed, it completes the names of fields, methods, constructor and classes
072: //
073:
074: public static AttrCompletionItem createNameCompletion(Method m,
075: String kindAndModifiers, boolean isInherited,
076: TypeParametersMapper mapper) {
077: boolean hasArgs = m.getParameterTypes().length > 0;
078: AttrCompletionItem aci = new AttrCompletionItem(
079: ElementKind.Method, kindAndModifiers, m.getName()
080: + "()", // + (hasArgs ? ")":""), // what will be completed. If no args, put the closing ")".
081: ClassUtils.toStringMethodForCompletion(m, mapper), // UI
082: ClassUtils.toStringReturnTypeForCompletion(m
083: .getGenericReturnType(), mapper), ClassUtils
084: .isDeprecated(m));
085:
086: if (hasArgs) {
087: aci.rewindCaret = 1;
088: aci.mapper = mapper;
089: }
090:
091: aci.setMember(m);
092: aci.inherited = isInherited;
093: aci.declaringClass = m.getDeclaringClass();
094:
095: return aci;
096: }
097:
098: public static AttrCompletionItem createNameCompletion(Field f,
099: String kindAndModifiers, boolean isInherited,
100: TypeParametersMapper mapper) {
101: AttrCompletionItem aci = new AttrCompletionItem(
102: ElementKind.Field, kindAndModifiers, f.getName(), // what will be completed
103: ClassUtils.toStringFieldForCompletion(f), // UI
104: ClassUtils.toStringReturnTypeForCompletion(f
105: .getGenericType(), mapper), ClassUtils
106: .isDeprecated(f));
107:
108: // no need to store the mapper
109:
110: aci.setMember(f);
111: aci.inherited = isInherited;
112: aci.declaringClass = f.getDeclaringClass();
113:
114: return aci;
115: }
116:
117: public static AttrCompletionItem createNameCompletion(
118: Constructor co, String kindAndModifiers,
119: boolean isInherited, TypeParametersMapper mapper) {
120: boolean hasArgs = co.getParameterTypes().length > 0;
121: AttrCompletionItem aci = new AttrCompletionItem(
122: ElementKind.Constructor, kindAndModifiers,
123: co.getName() + "()", // what will be completed
124: ClassUtils.toStringForCompletion(co, mapper), "",
125: ClassUtils.isDeprecated(co));
126:
127: if (hasArgs) {
128: aci.rewindCaret = 1;
129: aci.mapper = mapper;
130: }
131:
132: aci.setMember(co);
133: aci.inherited = isInherited;
134: aci.declaringClass = co.getDeclaringClass();
135:
136: return aci;
137: }
138:
139: public static AttrCompletionItem createNameCompletion(Class cl,
140: String kindAndModifiers, boolean isInherited) {
141: AttrCompletionItem aci = new AttrCompletionItem(
142: ElementKind.Class, kindAndModifiers, cl.getSimpleName()
143: + "(", cl.getSimpleName(), "", ClassUtils
144: .isDeprecated(cl));
145:
146: aci.setMember(cl);
147: aci.inherited = isInherited;
148: aci.declaringClass = cl.getDeclaringClass();
149:
150: return aci;
151: }
152:
153: public static AttrCompletionItem createInternalClassCompletion(
154: Class cl, String kindAndModifiers, boolean isInherited) {
155: AttrCompletionItem aci = new AttrCompletionItem(
156: ElementKind.Class, kindAndModifiers,
157: cl.getSimpleName(), cl.getSimpleName(), "", ClassUtils
158: .isDeprecated(cl));
159:
160: aci.setMember(cl);
161: aci.inherited = isInherited;
162: aci.declaringClass = cl.getDeclaringClass();
163:
164: return aci;
165: }
166:
167: public static AttrCompletionItem createNameCompletionForPackage(
168: FileItem packageItem) {
169: AttrCompletionItem aci = new AttrCompletionItem(
170: ElementKind.PackageNameFragment, "Package", packageItem
171: .getJavaPartName(), packageItem
172: .getJavaPartName(), "", false);
173:
174: aci.setMember(packageItem);
175: aci.inherited = false;
176:
177: return aci;
178: }
179:
180: public static AttrCompletionItem createNameCompletionForClass(
181: FileItem packageItem) {
182: AttrCompletionItem aci = new AttrCompletionItem(
183: ElementKind.Class, "Class", packageItem
184: .getJavaPartName(), packageItem
185: .getJavaPartName(), "", false);
186:
187: aci.setMember(packageItem);
188: aci.inherited = false;
189:
190: return aci;
191: }
192:
193: public static AttrCompletionItem createNameCompletionForClass(
194: FileItem classItem, String alreadyTyped) {
195: String partName = classItem.getJavaPartName();
196: AttrCompletionItem aci = new AttrCompletionItem(
197: ElementKind.Class, "Class", partName
198: .startsWith(alreadyTyped) ? partName
199: .substring(alreadyTyped.length()) : partName,
200: classItem.getJavaName(), // full name
201: "", false);
202:
203: aci.setMember(classItem);
204: aci.inherited = false;
205:
206: return aci;
207: }
208:
209: //
210: // Argument completions are used for methods and constructors
211: //
212:
213: public static AttrCompletionItem createArgumentsCompletion(
214: Method m, String kindAndModifiers, boolean isInherited,
215: TypeParametersMapper mapper) {
216: boolean hasArgs = m.getParameterTypes().length > 0;
217: AttrCompletionItem aci = new AttrCompletionItem(
218: ElementKind.Method, kindAndModifiers, "", ClassUtils
219: .toStringMethodArgsForCompletion(m, mapper), // UI
220: ClassUtils.toStringReturnTypeForCompletion(m
221: .getGenericReturnType(), mapper), false);
222:
223: if (hasArgs) {
224: aci.mapper = mapper;
225: }
226:
227: aci.setMember(m);
228: aci.inherited = isInherited;
229: aci.declaringClass = m.getDeclaringClass();
230:
231: return aci;
232: }
233:
234: public static AttrCompletionItem createArgumentsCompletion(
235: Constructor co, String kindAndModifiers,
236: boolean isInherited, TypeParametersMapper mapper) {
237: boolean hasArgs = co.getParameterTypes().length > 0;
238: AttrCompletionItem aci = new AttrCompletionItem(
239: ElementKind.Constructor, kindAndModifiers, "",
240: ClassUtils.toStringConstructorArgs(co, mapper), "",
241: false);
242:
243: if (hasArgs) {
244: aci.mapper = mapper;
245: }
246:
247: aci.setMember(co);
248: aci.inherited = isInherited;
249: aci.declaringClass = co.getDeclaringClass();
250:
251: return aci;
252: }
253:
254: /** Also defines the type (Method, Field, Package, ...)
255: */
256: public void setMember(Object member) {
257: this .member = member;
258: }
259:
260: /** Method, Field, Class, OR tide.sources.FileItem
261: */
262: public Object getMember() {
263: return member;
264: }
265:
266: public String getCompletion() {
267: return completion;
268: }
269:
270: /** ex: List<String> */
271: public String getReturnType() {
272: return returnType;
273: }
274:
275: public void setDeclaringClass(Class declaringClass,
276: boolean inherited) {
277: this .declaringClass = declaringClass;
278: this .inherited = inherited;
279: }
280:
281: public ElementKind getKind() {
282: return kind;
283: }
284:
285: public boolean isInherited() {
286: return inherited;
287: }
288:
289: public boolean isPublic() {
290: //TODO: a little bit nicer :-)
291: if (this .kindAndModifiers.indexOf("pub") >= 0)
292: return true;
293: // April2007: package and classes are "public"
294: if (this .getKind() == ElementKind.Class)
295: return true;
296: if (this .getKind() == ElementKind.InnerClass)
297: return true;
298: if (this .getKind() == ElementKind.PackageNameFragment)
299: return true;
300:
301: return false;
302: }
303:
304: //
305: // Factory constructor methods
306: //
307:
308: /** Java arrays are objects, with the special length method (without braces)
309: * it is a special case !
310: */
311: public static AttrCompletionItem arrayLengthItem() {
312: return new AttrCompletionItem(ElementKind.Method, "F pub",
313: "length", "length", "int", false,
314: "<html><body>The length of the array");
315: }
316:
317: /** Classes instances have the ".class" keyword available, as well as "this" and "super"
318: * it is a special case !
319: */
320: public static AttrCompletionItem classMemberItem(String className) {
321: return new AttrCompletionItem(ElementKind.Method, "F sta pub",
322: "class", "class", "Class<" + className + ">", false,
323: "<html><body>class keyword to access the Class "
324: + className);
325: }
326:
327: /** Classes instances have the ".class" keyword available, as well as "this" and "super"
328: * it is a special case !
329: */
330: public static AttrCompletionItem this MemberItem(String className) {
331: return new AttrCompletionItem(ElementKind.Method, "F", "this",
332: "this", className, false,
333: "<html><body>this keyword to access the current instance of "
334: + className);
335: }
336:
337: /** Classes instances have the ".class" keyword available, as well as "this" and "super"
338: * it is a special case !
339: */
340: public static AttrCompletionItem super MemberItem(
341: String super ClassName) {
342: return new AttrCompletionItem(ElementKind.Method, "F", "super",
343: "super", super ClassName, false,
344: "<html><body>super keyword to access the parent class "
345: + super ClassName);
346: }
347:
348: /* enums (class or value !) have a values() method !
349: * NOT NECESSARY, this is already seen by our reflection mechanism !
350: * since 1.6, this is in the javadoc
351: *
352: public static AttrCompletionItem enumValuesMemberItem(String enumClassName)
353: {
354: return new AttrCompletionItem(ElementKind.Method, "sta pub", "values()", "values()", enumClassName+"[]", false,
355: "<html><body>Returns an array containing the constants of this enum type, in the order they're declared."); // copied javadoc from 1.6
356: }*/
357:
358: public static AttrCompletionItem createParameter(String name,
359: String type) {
360: return new AttrCompletionItem(ElementKind.Field, "var", name,
361: name, type, false);
362: }
363:
364: public String getNameAndParams() {
365: return nameAndParams;
366: }
367:
368: public String getSuperCall() {
369: if (!getHasArgs())
370: return "super.();";
371: String np = getNameAndParams();
372: int posP = nameAndParams.indexOf('(');
373: String name = nameAndParams.substring(0, posP);
374: int posE = nameAndParams.indexOf(')');
375: StringBuilder args = new StringBuilder(nameAndParams.substring(
376: posP + 1, posE).trim()); // int a, double b, AAA.BBB<String, double> ccc, ...
377: SyntaxUtils.removeAllContents(args, '<', '>'); // remove type names
378:
379: String[] argslist = args.toString().split(",");
380: StringBuilder argsNames = new StringBuilder();
381: if (argslist.length > 0) {
382: for (String ai : argslist) {
383: argsNames.append(StringUtils.removeBeforeIncluded(
384: ai.trim(), " ").trim()); // "int a" => "a"
385: argsNames.append(", ");
386: }
387: argsNames.setLength(argsNames.length() - 2);
388:
389: }
390:
391: return "super." + name + "(" + argsNames + ");";
392: }
393:
394: public void setNameAndParams(String a) {
395: this .nameAndParams = a;
396: }
397:
398: /** Used to distinguish between methods and fields.
399: * no sense in the arguments completion.
400: */
401: public boolean getHasArgs() {
402: int posP = nameAndParams.indexOf('(');
403: if (posP < 0)
404: return false;
405: int posE = nameAndParams.indexOf(')');
406: String a = nameAndParams.substring(posP + 1, posE).trim();
407: if (a.length() > 0)
408: return true;
409: return false;
410: }
411:
412: /** Used for debug purposes.
413: */
414: @Override
415: public final String toString() {
416: StringBuilder sb = new StringBuilder();
417: sb.append("AttrCompletionItem " + this .kindAndModifiers + " "
418: + this .nameAndParams);
419: return sb.toString();
420: }
421:
422: /** helps a little bit the GC
423: */
424: public void freeMem_() {
425:
426: mapper = null;
427: member = null;
428: kind = null;
429: this.declaringClass = null;
430: jdoc = null;
431:
432: }
433:
434: }
|