1 | /******************************************************************************* |
2 | * Copyright (c) 2008, 2009 IBM Corporation and others. |
3 | * All rights reserved. This program and the accompanying materials |
4 | * are made available under the terms of the Eclipse Public License v1.0 |
5 | * which accompanies this distribution, and is available at |
6 | * http://www.eclipse.org/legal/epl-v10.html |
7 | * |
8 | * Contributors: |
9 | * IBM Corporation - initial API and implementation |
10 | *******************************************************************************/ |
11 | package org.eclipse.pde.api.tools.internal.model; |
12 | |
13 | import java.util.HashMap; |
14 | import java.util.HashSet; |
15 | import java.util.Iterator; |
16 | import java.util.LinkedHashMap; |
17 | import java.util.LinkedList; |
18 | import java.util.List; |
19 | import java.util.Map; |
20 | |
21 | import org.eclipse.core.runtime.CoreException; |
22 | import org.eclipse.core.runtime.IProgressMonitor; |
23 | import org.eclipse.core.runtime.IStatus; |
24 | import org.eclipse.core.runtime.Status; |
25 | import org.eclipse.pde.api.tools.internal.builder.ReferenceExtractor; |
26 | import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; |
27 | import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor; |
28 | import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor; |
29 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; |
30 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement; |
31 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiField; |
32 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod; |
33 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiType; |
34 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot; |
35 | import org.eclipse.pde.api.tools.internal.util.Signatures; |
36 | import org.eclipse.pde.api.tools.internal.util.Util; |
37 | import org.objectweb.asm.ClassReader; |
38 | import org.objectweb.asm.Opcodes; |
39 | |
40 | import com.ibm.icu.text.MessageFormat; |
41 | |
42 | /** |
43 | * Base implementation of {@link IApiType} |
44 | * |
45 | * @since 1.0.0 |
46 | * @noextend This class is not intended to be sub-classed by clients. |
47 | * @noinstantiate This class is not intended to be instantiated by clients. |
48 | */ |
49 | public class ApiType extends ApiMember implements IApiType { |
50 | |
51 | private String fSuperclassName; |
52 | private String[] fSuperInterfaceNames; |
53 | private String fEnclosingTypeName; |
54 | private String fSimpleName; |
55 | |
56 | private static final IApiMethod[] EMPTY_METHODS = new IApiMethod[0]; |
57 | private static final IApiField[] EMPTY_FIELDS = new IApiField[0]; |
58 | private static final IApiType[] EMPTY_TYPES = new IApiType[0]; |
59 | |
60 | /* |
61 | * Use to tag fEnclosingMethodName and fEnclosingMethodSignature when there is no enclosing method |
62 | * but the EnclosingMethodAttribute is set (anonymous type in a field initializer). |
63 | */ |
64 | private static final String NO_ENCLOSING_METHOD = Util.EMPTY_STRING; |
65 | |
66 | /** |
67 | * Maps field name to field element. |
68 | */ |
69 | private Map fFields; |
70 | /** |
71 | * Maps method name/signature pair to method element. |
72 | */ |
73 | private LinkedHashMap fMethods; |
74 | |
75 | /** |
76 | * Map of member type names to class file (or null until resolved) |
77 | */ |
78 | private Map fMemberTypes; |
79 | |
80 | /** |
81 | * Cached descriptor |
82 | */ |
83 | private IReferenceTypeDescriptor fHandle; |
84 | |
85 | /** |
86 | * Cached superclass or <code>null</code> |
87 | */ |
88 | private IApiType fSuperclass; |
89 | |
90 | /** |
91 | * Cached super interfaces or <code>null</code> |
92 | */ |
93 | private IApiType[] fSuperInterfaces; |
94 | |
95 | /** |
96 | * The storage this type structure originated from |
97 | */ |
98 | private IApiTypeRoot fStorage; |
99 | |
100 | /** |
101 | * The signature of the enclosing method if this is a local type |
102 | */ |
103 | private String fEnclosingMethodSignature = null; |
104 | |
105 | /** |
106 | * The name of the method that encloses this type if it is local |
107 | */ |
108 | private String fEnclosingMethodName = null; |
109 | |
110 | /** |
111 | * If this is an anonymous class or not |
112 | */ |
113 | private boolean fAnonymous = false; |
114 | |
115 | /** |
116 | * If this is a local type or not (class defined in a method) |
117 | */ |
118 | private boolean fLocal = false; |
119 | |
120 | /** |
121 | * If this is a member type or not (class defined in a method) |
122 | */ |
123 | private boolean fMemberType = false; |
124 | |
125 | /** |
126 | * cached enclosing type once it has been successfully calculated |
127 | */ |
128 | private IApiType fEnclosingType = null; |
129 | |
130 | /** |
131 | * The method that encloses this type |
132 | */ |
133 | private IApiMethod fEnclosingMethod = null; |
134 | |
135 | /** |
136 | * Creates an API type. Note that if an API component is not specified, |
137 | * then some operations will not be available (navigating super types, |
138 | * member types, etc). |
139 | * |
140 | * @param parent the parent {@link IApiElement} or <code>null</code> if none |
141 | * @param name the name of the type |
142 | * @param signature the signature of the type |
143 | * @param genericSig the generic signature of the type |
144 | * @param flags the flags for the type |
145 | * @param enclosingName |
146 | * @param storage the storage this content was generated from |
147 | */ |
148 | public ApiType(IApiElement parent, String name, String signature, String genericSig, int flags, String enclosingName, IApiTypeRoot storage) { |
149 | super(parent, name, signature, genericSig, IApiElement.TYPE, flags); |
150 | fEnclosingTypeName = enclosingName; |
151 | fStorage = storage; |
152 | } |
153 | |
154 | /* (non-Javadoc) |
155 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#extractReferences(int, org.eclipse.core.runtime.IProgressMonitor) |
156 | */ |
157 | public List extractReferences(int referenceMask, IProgressMonitor monitor) throws CoreException { |
158 | HashSet references = new HashSet(); |
159 | ReferenceExtractor extractor = new ReferenceExtractor(this, references, referenceMask); |
160 | ClassReader reader = new ClassReader(((AbstractApiTypeRoot)fStorage).getContents()); |
161 | reader.accept(extractor, ClassReader.SKIP_FRAMES); |
162 | return new LinkedList(references); |
163 | } |
164 | |
165 | /* (non-Javadoc) |
166 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getField(java.lang.String) |
167 | */ |
168 | public IApiField getField(String name) { |
169 | if (fFields != null) { |
170 | return (IApiField) fFields.get(name); |
171 | } |
172 | return null; |
173 | } |
174 | |
175 | /* (non-Javadoc) |
176 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getFields() |
177 | */ |
178 | public IApiField[] getFields() { |
179 | if (fFields != null) { |
180 | return (IApiField[]) fFields.values().toArray(new IApiField[fFields.size()]); |
181 | } |
182 | return EMPTY_FIELDS; |
183 | } |
184 | |
185 | /* (non-Javadoc) |
186 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiMember#getPackageName() |
187 | */ |
188 | public String getPackageName() { |
189 | return getName().substring(0, getName().lastIndexOf('.')); |
190 | } |
191 | |
192 | /** |
193 | * Used when building a type structure. |
194 | * |
195 | * @param name method name |
196 | * @param signature method signature |
197 | * @param genericSig |
198 | * @param modifiers method modifiers |
199 | * @param exceptions names of thrown exceptions |
200 | */ |
201 | public ApiMethod addMethod(String name, String signature, String genericSig, int modifiers, String[] exceptions) { |
202 | if (fMethods == null) { |
203 | fMethods = new LinkedHashMap(); |
204 | } |
205 | ApiMethod method = new ApiMethod(this, name, signature, genericSig, modifiers, exceptions); |
206 | fMethods.put(new MethodKey(name, signature), method); |
207 | return method; |
208 | } |
209 | |
210 | /** |
211 | * Used when building a type structure. |
212 | * |
213 | * @param name field name |
214 | * @param signature field signature |
215 | * @param genericSig |
216 | * @param modifiers field modifiers |
217 | * @param value constant value or <code>null</code> if none |
218 | */ |
219 | public ApiField addField(String name, String signature, String genericSig, int modifiers, Object value) { |
220 | if (fFields == null) { |
221 | fFields = new HashMap(); |
222 | } |
223 | ApiField field = new ApiField(this, name, signature, genericSig, modifiers, value); |
224 | fFields.put(name, field); |
225 | return field; |
226 | } |
227 | |
228 | /* (non-Javadoc) |
229 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getMethod(java.lang.String, java.lang.String) |
230 | */ |
231 | public IApiMethod getMethod(String name, String signature) { |
232 | if (fMethods != null) { |
233 | return (IApiMethod) fMethods.get(new MethodKey(name, signature)); |
234 | } |
235 | return null; |
236 | } |
237 | |
238 | |
239 | /* (non-Javadoc) |
240 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getMethods() |
241 | */ |
242 | public IApiMethod[] getMethods() { |
243 | if (fMethods != null) { |
244 | return (IApiMethod[]) fMethods.values().toArray(new IApiMethod[fMethods.size()]); |
245 | } |
246 | return EMPTY_METHODS; |
247 | } |
248 | |
249 | /* (non-Javadoc) |
250 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getSuperInterfaceNames() |
251 | */ |
252 | public String[] getSuperInterfaceNames() { |
253 | return fSuperInterfaceNames; |
254 | } |
255 | |
256 | public void setSuperInterfaceNames(String[] names) { |
257 | fSuperInterfaceNames = names; |
258 | } |
259 | |
260 | /* (non-Javadoc) |
261 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getSuperInterfaces() |
262 | */ |
263 | public IApiType[] getSuperInterfaces() throws CoreException { |
264 | String[] names = getSuperInterfaceNames(); |
265 | if (names == null) { |
266 | return EMPTY_TYPES; |
267 | } |
268 | if (fSuperInterfaces == null) { |
269 | IApiType[] interfaces = new IApiType[names.length]; |
270 | for (int i = 0; i < interfaces.length; i++) { |
271 | interfaces[i] = resolveType(names[i]); |
272 | if (interfaces[i] == null) { |
273 | throw new CoreException( |
274 | new Status( |
275 | IStatus.ERROR, |
276 | ApiPlugin.PLUGIN_ID, |
277 | ApiPlugin.REPORT_RESOLUTION_ERRORS, |
278 | MessageFormat.format(Messages.ApiType_0, new String[]{names[i], getName()}), |
279 | null)); |
280 | } |
281 | } |
282 | fSuperInterfaces = interfaces; |
283 | } |
284 | return fSuperInterfaces; |
285 | } |
286 | |
287 | /* (non-Javadoc) |
288 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getSuperclass() |
289 | */ |
290 | public IApiType getSuperclass() throws CoreException { |
291 | String name = getSuperclassName(); |
292 | if (name == null) { |
293 | return null; |
294 | } |
295 | if (fSuperclass == null) { |
296 | fSuperclass = resolveType(name); |
297 | if (fSuperclass == null) { |
298 | throw new CoreException(new Status( |
299 | IStatus.ERROR, |
300 | ApiPlugin.PLUGIN_ID, |
301 | ApiPlugin.REPORT_RESOLUTION_ERRORS, |
302 | MessageFormat.format(Messages.ApiType_1, new String[]{name, getName()}), |
303 | null)); |
304 | } |
305 | } |
306 | return fSuperclass; |
307 | } |
308 | |
309 | /** |
310 | * Resolves and returns the specified fully qualified type name or <code>null</code> |
311 | * if none. |
312 | * |
313 | * @param qName qualified name |
314 | * @return type or <code>null</code> |
315 | * @throws CoreException if unable to resolve |
316 | */ |
317 | private IApiType resolveType(String qName) throws CoreException { |
318 | if (getApiComponent() == null) { |
319 | requiresApiComponent(); |
320 | } |
321 | String packageName = Signatures.getPackageName(qName); |
322 | IApiComponent[] components = getApiComponent().getBaseline(). |
323 | resolvePackage(getApiComponent(), packageName); |
324 | IApiTypeRoot result = Util.getClassFile(components, qName); |
325 | if (result != null) { |
326 | return result.getStructure(); |
327 | } |
328 | return null; |
329 | } |
330 | |
331 | /** |
332 | * Throws an exception due to the fact an API component was not provided when this type |
333 | * was created and is now required to perform navigation or resolution. |
334 | * |
335 | * @throws CoreException |
336 | */ |
337 | private void requiresApiComponent() throws CoreException { |
338 | throw new CoreException(new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, Messages.ApiType_2)); |
339 | } |
340 | |
341 | /* (non-Javadoc) |
342 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getSuperclassName() |
343 | */ |
344 | public String getSuperclassName() { |
345 | return fSuperclassName; |
346 | } |
347 | |
348 | public void setSuperclassName(String superName) { |
349 | fSuperclassName = superName; |
350 | } |
351 | |
352 | public void setSimpleName(String simpleName) { |
353 | fSimpleName = simpleName; |
354 | } |
355 | |
356 | /* (non-Javadoc) |
357 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isAnnotation() |
358 | */ |
359 | public boolean isAnnotation() { |
360 | return (getModifiers() & Opcodes.ACC_ANNOTATION) != 0; |
361 | } |
362 | |
363 | /* (non-Javadoc) |
364 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isAnonymous() |
365 | */ |
366 | public boolean isAnonymous() { |
367 | return fAnonymous; |
368 | } |
369 | |
370 | /* (non-Javadoc) |
371 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isLocal() |
372 | */ |
373 | public boolean isLocal() { |
374 | return fLocal; |
375 | } |
376 | |
377 | /* (non-Javadoc) |
378 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getTypeRoot() |
379 | */ |
380 | public IApiTypeRoot getTypeRoot() { |
381 | return fStorage; |
382 | } |
383 | |
384 | /** |
385 | * Used when building a type structure. |
386 | */ |
387 | public void setAnonymous() { |
388 | fAnonymous = true; |
389 | } |
390 | |
391 | /** |
392 | * Used when building a type structure. |
393 | */ |
394 | public void setMemberType() { |
395 | fMemberType = true; |
396 | } |
397 | |
398 | /** |
399 | * Used when building a type structure for pre-1.5 sources |
400 | */ |
401 | public void setLocal() { |
402 | fLocal = true; |
403 | } |
404 | |
405 | /** |
406 | * Sets the signature of the method that encloses this local type |
407 | * @param signature the signature of the method. |
408 | * @see org.eclipse.jdt.core.Signature for more information |
409 | */ |
410 | public void setEnclosingMethodInfo(String name, String signature) { |
411 | if (name != null) { |
412 | fEnclosingMethodName = name; |
413 | } else { |
414 | fEnclosingMethodName = NO_ENCLOSING_METHOD; |
415 | } |
416 | if (signature != null) { |
417 | fEnclosingMethodSignature = signature; |
418 | } else { |
419 | fEnclosingMethodSignature = NO_ENCLOSING_METHOD; |
420 | } |
421 | } |
422 | |
423 | /* (non-Javadoc) |
424 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getEnclosingMethod() |
425 | */ |
426 | public IApiMethod getEnclosingMethod() { |
427 | if(fEnclosingMethod == null) { |
428 | try { |
429 | IApiType enclosingType = getEnclosingType(); |
430 | if(fEnclosingMethodName != null) { |
431 | if (fEnclosingMethodName != NO_ENCLOSING_METHOD) { |
432 | fEnclosingMethod = enclosingType.getMethod(fEnclosingMethodName, fEnclosingMethodSignature); |
433 | } |
434 | } else { |
435 | TypeStructureBuilder.setEnclosingMethod(enclosingType, this); |
436 | if(fEnclosingMethodName != null) { |
437 | fEnclosingMethod = enclosingType.getMethod(fEnclosingMethodName, fEnclosingMethodSignature); |
438 | } else { |
439 | // this prevents from trying to retrieve again the enclosing method when there is none |
440 | fEnclosingMethodName = NO_ENCLOSING_METHOD; |
441 | } |
442 | } |
443 | } |
444 | catch (CoreException ce) {} |
445 | } |
446 | return fEnclosingMethod; |
447 | } |
448 | |
449 | /* (non-Javadoc) |
450 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isClass() |
451 | */ |
452 | public boolean isClass() { |
453 | return (getModifiers() & ( |
454 | Opcodes.ACC_ANNOTATION | |
455 | Opcodes.ACC_ENUM | |
456 | Opcodes.ACC_INTERFACE)) == 0; |
457 | } |
458 | |
459 | /* (non-Javadoc) |
460 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isEnum() |
461 | */ |
462 | public boolean isEnum() { |
463 | return (getModifiers() & Opcodes.ACC_ENUM) != 0; |
464 | } |
465 | |
466 | /* (non-Javadoc) |
467 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isInterface() |
468 | */ |
469 | public boolean isInterface() { |
470 | return (getModifiers() & Opcodes.ACC_INTERFACE) != 0; |
471 | } |
472 | |
473 | /* (non-Javadoc) |
474 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#isMemberType() |
475 | */ |
476 | public boolean isMemberType() { |
477 | return fMemberType; |
478 | } |
479 | |
480 | /* (non-Javadoc) |
481 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiMember#getHandle() |
482 | */ |
483 | public IMemberDescriptor getHandle() { |
484 | if (fHandle == null) { |
485 | fHandle = Util.getType(getName()); |
486 | } |
487 | return fHandle; |
488 | } |
489 | |
490 | /* (non-Javadoc) |
491 | * @see java.lang.Object#equals(java.lang.Object) |
492 | */ |
493 | public boolean equals(Object obj) { |
494 | if (obj instanceof IApiType) { |
495 | IApiType type = (IApiType) obj; |
496 | if (getApiComponent() == null) { |
497 | return type.getApiComponent() == null && |
498 | getName().equals(type.getName()); |
499 | } |
500 | return getApiComponent().equals(type.getApiComponent()) && |
501 | getName().equals(type.getName()); |
502 | } |
503 | return false; |
504 | } |
505 | |
506 | /* (non-Javadoc) |
507 | * @see java.lang.Object#hashCode() |
508 | */ |
509 | public int hashCode() { |
510 | IApiComponent component = getApiComponent(); |
511 | if (component == null) { |
512 | return getName().hashCode(); |
513 | } |
514 | return component.hashCode() + getName().hashCode(); |
515 | } |
516 | |
517 | /** |
518 | * Used when building a type structure. |
519 | * |
520 | * @param name member type name |
521 | */ |
522 | public void addMemberType(String name, int modifiers) { |
523 | if (fMemberTypes == null) { |
524 | fMemberTypes = new HashMap(); |
525 | } |
526 | int index = name.lastIndexOf('$'); |
527 | String simpleName = name.substring(index + 1); |
528 | fMemberTypes.put(simpleName, null); |
529 | } |
530 | |
531 | /* (non-Javadoc) |
532 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getMemberType(java.lang.String) |
533 | */ |
534 | public IApiType getMemberType(String simpleName) throws CoreException { |
535 | if (fMemberTypes == null) { |
536 | return null; |
537 | } |
538 | if (getApiComponent() == null) { |
539 | requiresApiComponent(); |
540 | } |
541 | if (fMemberTypes.containsKey(simpleName)) { |
542 | IApiTypeRoot file = (IApiTypeRoot) fMemberTypes.get(simpleName); |
543 | if (file == null) { |
544 | // resolve |
545 | StringBuffer qName = new StringBuffer(); |
546 | qName.append(getName()); |
547 | qName.append('$'); |
548 | qName.append(simpleName); |
549 | file = getApiComponent().findTypeRoot(qName.toString()); |
550 | if (file == null) { |
551 | throw new CoreException(new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, |
552 | MessageFormat.format(Messages.ApiType_3, |
553 | new String[]{simpleName, getName()}))); |
554 | } |
555 | fMemberTypes.put(simpleName, file); |
556 | } |
557 | return file.getStructure(); |
558 | } |
559 | return null; |
560 | } |
561 | |
562 | /* (non-Javadoc) |
563 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getMemberTypes() |
564 | */ |
565 | public IApiType[] getMemberTypes() throws CoreException { |
566 | if (fMemberTypes == null) { |
567 | return EMPTY_TYPES; |
568 | } |
569 | IApiType[] members = new IApiType[fMemberTypes.size()]; |
570 | Iterator iterator = fMemberTypes.keySet().iterator(); |
571 | int index = 0; |
572 | while (iterator.hasNext()) { |
573 | String name = (String) iterator.next(); |
574 | members[index] = getMemberType(name); |
575 | index++; |
576 | } |
577 | return members; |
578 | } |
579 | |
580 | /** |
581 | * @see java.lang.Object#toString() |
582 | */ |
583 | public String toString() { |
584 | StringBuffer buffer = new StringBuffer(); |
585 | buffer |
586 | .append("Type : access(") //$NON-NLS-1$ |
587 | .append(getModifiers()) |
588 | .append(") ") //$NON-NLS-1$ |
589 | .append(getName()); |
590 | if (getSuperclassName() != null) { |
591 | buffer |
592 | .append(" superclass: ") //$NON-NLS-1$ |
593 | .append(getSuperclassName()); |
594 | } |
595 | if (getSuperInterfaceNames() != null) { |
596 | buffer.append(" interfaces : "); //$NON-NLS-1$ |
597 | if (getSuperInterfaceNames().length > 0) { |
598 | for (int i = 0; i < getSuperInterfaceNames().length; i++) { |
599 | if (i > 0) buffer.append(','); |
600 | buffer.append(getSuperInterfaceNames()[i]); |
601 | } |
602 | } else { |
603 | buffer.append("none"); //$NON-NLS-1$ |
604 | } |
605 | } |
606 | buffer.append(';').append(Util.LINE_DELIMITER); |
607 | if (getGenericSignature() != null) { |
608 | buffer |
609 | .append(" Signature : ") //$NON-NLS-1$ |
610 | .append(getGenericSignature()).append(Util.LINE_DELIMITER); |
611 | } |
612 | buffer.append(Util.LINE_DELIMITER).append("Methods : ").append(Util.LINE_DELIMITER); //$NON-NLS-1$ |
613 | IApiMethod[] methods = getMethods(); |
614 | for (int i = 0; i < methods.length; i++) { |
615 | buffer.append(methods[i]); |
616 | } |
617 | buffer.append(Util.LINE_DELIMITER).append("Fields : ").append(Util.LINE_DELIMITER); //$NON-NLS-1$ |
618 | IApiField[] fields = getFields(); |
619 | for (int i = 0; i < fields.length; i++) { |
620 | buffer.append(fields[i]); |
621 | } |
622 | return String.valueOf(buffer); |
623 | } |
624 | |
625 | /* (non-Javadoc) |
626 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiType#getSimpleName() |
627 | */ |
628 | public String getSimpleName() { |
629 | if (this.isAnonymous()) { |
630 | return null; |
631 | } |
632 | if (this.isLocal() || this.isMemberType()) { |
633 | return this.fSimpleName; |
634 | } |
635 | String name = getName(); |
636 | int index = name.lastIndexOf('.'); |
637 | if (index != -1) { |
638 | return name.substring(index + 1); |
639 | } |
640 | return name; |
641 | } |
642 | /* (non-Javadoc) |
643 | * @see org.eclipse.pde.api.tools.internal.model.ApiMember#getEnclosingType() |
644 | */ |
645 | public IApiType getEnclosingType() throws CoreException { |
646 | if(fEnclosingType != null) { |
647 | return fEnclosingType; |
648 | } |
649 | if(fEnclosingTypeName != null) { |
650 | IApiTypeRoot root = getApiComponent().findTypeRoot(processEnclosingTypeName()); |
651 | if(root != null) { |
652 | fEnclosingType = root.getStructure(); |
653 | } |
654 | } |
655 | return fEnclosingType; |
656 | } |
657 | |
658 | private String processEnclosingTypeName() { |
659 | if(isLocal() || isAnonymous()) { |
660 | int idx = fEnclosingTypeName.lastIndexOf('$'); |
661 | if(Character.isDigit(fEnclosingTypeName.charAt(idx + 1))) { |
662 | return fEnclosingTypeName.substring(0, idx); |
663 | } |
664 | } |
665 | return fEnclosingTypeName; |
666 | } |
667 | } |