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.builder; |
12 | |
13 | import org.eclipse.core.runtime.CoreException; |
14 | import org.eclipse.jdt.core.Flags; |
15 | import org.eclipse.pde.api.tools.internal.model.StubApiComponent; |
16 | import org.eclipse.pde.api.tools.internal.provisional.Factory; |
17 | import org.eclipse.pde.api.tools.internal.provisional.IApiAccess; |
18 | import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations; |
19 | import org.eclipse.pde.api.tools.internal.provisional.IApiDescription; |
20 | import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers; |
21 | import org.eclipse.pde.api.tools.internal.provisional.builder.IReference; |
22 | import org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor; |
23 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; |
24 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember; |
25 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod; |
26 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiType; |
27 | import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot; |
28 | import org.eclipse.pde.api.tools.internal.search.IReferenceDescriptor; |
29 | import org.eclipse.pde.api.tools.internal.search.ReferenceDescriptor; |
30 | import org.eclipse.pde.api.tools.internal.search.UseReportConverter; |
31 | import org.eclipse.pde.api.tools.internal.util.Signatures; |
32 | import org.eclipse.pde.api.tools.internal.util.Util; |
33 | |
34 | /** |
35 | * Implementation of a reference from one member to another. |
36 | * |
37 | * @since 1.0.0 |
38 | */ |
39 | public class Reference implements IReference { |
40 | |
41 | /** |
42 | * Line number where the reference occurred. |
43 | */ |
44 | private int fSourceLine = -1; |
45 | |
46 | /** |
47 | * Member where the reference occurred. |
48 | */ |
49 | private IApiMember fSourceMember; |
50 | |
51 | /** |
52 | * One of the valid {@link org.eclipse.pde.api.tools.internal.provisional.search.ReferenceModifiers} |
53 | */ |
54 | private int fKind; |
55 | |
56 | /** |
57 | * One of the valid type, method, field. |
58 | */ |
59 | private int fType; |
60 | |
61 | /** |
62 | * Name of the referenced type |
63 | */ |
64 | private String fTypeName; |
65 | |
66 | /** |
67 | * Name of the referenced member or <code>null</code> |
68 | */ |
69 | private String fMemberName; |
70 | |
71 | /** |
72 | * Signature of the referenced method or <code>null</code> |
73 | */ |
74 | private String fSignature; |
75 | |
76 | /** |
77 | * Resolved reference or <code>null</code> |
78 | */ |
79 | private IApiMember fResolved; |
80 | |
81 | /** |
82 | * Resolvable status |
83 | */ |
84 | private boolean fStatus = true; |
85 | |
86 | /* (non-Javadoc) |
87 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getLineNumber() |
88 | */ |
89 | public int getLineNumber() { |
90 | return fSourceLine; |
91 | } |
92 | |
93 | /* (non-Javadoc) |
94 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getMember() |
95 | */ |
96 | public IApiMember getMember() { |
97 | return fSourceMember; |
98 | } |
99 | |
100 | /* (non-Javadoc) |
101 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferenceKind() |
102 | */ |
103 | public int getReferenceKind() { |
104 | return fKind; |
105 | } |
106 | |
107 | /* (non-Javadoc) |
108 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferenceType() |
109 | */ |
110 | public int getReferenceType() { |
111 | return fType; |
112 | } |
113 | |
114 | /* (non-Javadoc) |
115 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferencedMember() |
116 | */ |
117 | public IApiMember getResolvedReference() { |
118 | return fResolved; |
119 | } |
120 | |
121 | /* (non-Javadoc) |
122 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferencedMemberName() |
123 | */ |
124 | public String getReferencedMemberName() { |
125 | return fMemberName; |
126 | } |
127 | |
128 | /* (non-Javadoc) |
129 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferencedSignature() |
130 | */ |
131 | public String getReferencedSignature() { |
132 | return fSignature; |
133 | } |
134 | |
135 | /* (non-Javadoc) |
136 | * @see org.eclipse.pde.api.tools.internal.provisional.model.IReference#getReferencedTypeName() |
137 | */ |
138 | public String getReferencedTypeName() { |
139 | return fTypeName; |
140 | } |
141 | |
142 | /** |
143 | * Creates and returns a method reference. |
144 | * |
145 | * @param origin where the reference occurred from |
146 | * @param typeName name of the referenced type where virtual method lookup begins |
147 | * @param methodName name of the referenced method |
148 | * @param signature signature of the referenced method |
149 | * @param kind kind of method reference |
150 | */ |
151 | public static Reference methodReference(IApiMember origin, String typeName, String methodName, String signature, int kind) { |
152 | Reference ref = new Reference(); |
153 | ref.fSourceMember = origin; |
154 | ref.fTypeName = typeName; |
155 | ref.fMemberName = methodName; |
156 | ref.fSignature = signature; |
157 | ref.fKind = kind; |
158 | ref.fType = IReference.T_METHOD_REFERENCE; |
159 | return ref; |
160 | } |
161 | |
162 | /** |
163 | * Creates and returns a field reference. |
164 | * |
165 | * @param origin where the reference occurred from |
166 | * @param typeName name of the referenced type where field lookup begins |
167 | * @param fieldName name of the referenced field |
168 | * @param kind kind of field reference |
169 | */ |
170 | public static Reference fieldReference(IApiMember origin, String typeName, String fieldName, int kind) { |
171 | Reference ref = new Reference(); |
172 | ref.fSourceMember = origin; |
173 | ref.fTypeName = typeName; |
174 | ref.fMemberName = fieldName; |
175 | ref.fKind = kind; |
176 | ref.fType = IReference.T_FIELD_REFERENCE; |
177 | return ref; |
178 | } |
179 | |
180 | /** |
181 | * Creates and returns a type reference. |
182 | * |
183 | * @param origin where the reference occurred from |
184 | * @param typeName name of the referenced type |
185 | * @param kind kind of reference |
186 | */ |
187 | public static Reference typeReference(IApiMember origin, String typeName, int kind) { |
188 | Reference ref = new Reference(); |
189 | ref.fSourceMember = origin; |
190 | ref.fTypeName = typeName; |
191 | ref.fKind = kind; |
192 | ref.fType = IReference.T_TYPE_REFERENCE; |
193 | return ref; |
194 | } |
195 | |
196 | /** |
197 | * Creates and returns a type reference. |
198 | * |
199 | * @param origin where the reference occurred from |
200 | * @param typeName name of the referenced type |
201 | * @param signature extra type signature information |
202 | * @param kind kind of reference |
203 | */ |
204 | public static Reference typeReference(IApiMember origin, String typeName, String signature, int kind) { |
205 | Reference ref = typeReference(origin, typeName, kind); |
206 | ref.fSignature = signature; |
207 | return ref; |
208 | } |
209 | |
210 | /** |
211 | * Sets the line number - used by the reference extractor. |
212 | * |
213 | * @param line line number |
214 | */ |
215 | void setLineNumber(int line) { |
216 | fSourceLine = line; |
217 | } |
218 | |
219 | /** |
220 | * Resolves this reference in the given profile. |
221 | * |
222 | * @param engine search engine resolving the reference |
223 | * @throws CoreException |
224 | */ |
225 | public void resolve() throws CoreException { |
226 | if (!this.fStatus) { |
227 | return; |
228 | } |
229 | if (fResolved == null) { |
230 | IApiComponent sourceComponent = getMember().getApiComponent(); |
231 | if(sourceComponent != null) { |
232 | IApiTypeRoot result = Util.getClassFile( |
233 | sourceComponent.getBaseline().resolvePackage(sourceComponent, Signatures.getPackageName(getReferencedTypeName())), |
234 | getReferencedTypeName()); |
235 | if(result != null) { |
236 | IApiType type = result.getStructure(); |
237 | if(type == null) { |
238 | //cannot resolve a type that is in a bad classfile |
239 | return; |
240 | } |
241 | switch (getReferenceType()) { |
242 | case IReference.T_TYPE_REFERENCE: |
243 | fResolved = type; |
244 | break; |
245 | case IReference.T_FIELD_REFERENCE: |
246 | fResolved = type.getField(getReferencedMemberName()); |
247 | break; |
248 | case IReference.T_METHOD_REFERENCE: |
249 | resolveVirtualMethod(type, getReferencedMemberName(), getReferencedSignature()); |
250 | break; |
251 | } |
252 | } |
253 | } |
254 | } |
255 | // TODO: throw exception on failure |
256 | } |
257 | public boolean resolve(int eeValue) throws CoreException { |
258 | IApiComponent sourceComponent = StubApiComponent.getStubApiComponent(eeValue); |
259 | if (sourceComponent == null) { |
260 | // if there is no source component for the ee value, the reference is considered as resolved |
261 | return true; |
262 | } |
263 | IApiTypeRoot result = Util.getClassFile( |
264 | new IApiComponent[] { sourceComponent }, |
265 | getReferencedTypeName()); |
266 | if(result != null) { |
267 | IApiType type = result.getStructure(); |
268 | if(type == null) { |
269 | return false; |
270 | } |
271 | switch (getReferenceType()) { |
272 | case IReference.T_TYPE_REFERENCE: |
273 | return true; |
274 | case IReference.T_FIELD_REFERENCE: |
275 | return type.getField(getReferencedMemberName()) != null; |
276 | case IReference.T_METHOD_REFERENCE: |
277 | return resolveVirtualMethod0(sourceComponent, type, getReferencedMemberName(), getReferencedSignature()); |
278 | } |
279 | } |
280 | return false; |
281 | } |
282 | /** |
283 | * Resolves a virtual method and returns whether the method lookup was successful. |
284 | * We need to resolve the actual type that implements the method - i.e. do the virtual |
285 | * method lookup. |
286 | * |
287 | * @param callSiteComponent the component where the method call site was located |
288 | * @param typeName referenced type name |
289 | * @param methodName referenced method name |
290 | * @param methodSignature referenced method signature |
291 | * @returns whether the lookup succeeded |
292 | * @throws CoreException if something goes terribly wrong |
293 | */ |
294 | private boolean resolveVirtualMethod(IApiType type, String methodName, String methodSignature) throws CoreException { |
295 | IApiMethod target = type.getMethod(methodName, methodSignature); |
296 | if (target != null) { |
297 | if (target.isSynthetic()) { |
298 | // don't resolve references to synthetic methods |
299 | return false; |
300 | } else { |
301 | fResolved = target; |
302 | return true; |
303 | } |
304 | } |
305 | if (getReferenceKind() == IReference.REF_INTERFACEMETHOD) { |
306 | // resolve method in super interfaces rather than class |
307 | IApiType[] interfaces = type.getSuperInterfaces(); |
308 | if (interfaces != null) { |
309 | for (int i = 0; i < interfaces.length; i++) { |
310 | if (resolveVirtualMethod(interfaces[i], methodName, methodSignature)) { |
311 | return true; |
312 | } |
313 | } |
314 | } |
315 | } else { |
316 | IApiType superT = type.getSuperclass(); |
317 | if (superT != null) { |
318 | return resolveVirtualMethod(superT, methodName, methodSignature); |
319 | } |
320 | } |
321 | return false; |
322 | } |
323 | |
324 | /** |
325 | * Resolves a virtual method and returns whether the method lookup was successful. |
326 | * We need to resolve the actual type that implements the method - i.e. do the virtual |
327 | * method lookup. |
328 | * |
329 | * @param callSiteComponent the component where the method call site was located |
330 | * @param typeName referenced type name |
331 | * @param methodName referenced method name |
332 | * @param methodSignature referenced method signature |
333 | * @returns whether the lookup succeeded |
334 | * @throws CoreException if something goes terribly wrong |
335 | */ |
336 | private boolean resolveVirtualMethod0(IApiComponent sourceComponent, IApiType type, String methodName, String methodSignature) throws CoreException { |
337 | IApiMethod target = type.getMethod(methodName, methodSignature); |
338 | if (target != null) { |
339 | if (target.isSynthetic()) { |
340 | // don't resolve references to synthetic methods |
341 | return false; |
342 | } else { |
343 | return true; |
344 | } |
345 | } |
346 | switch(this.fKind) { |
347 | case IReference.REF_INTERFACEMETHOD : |
348 | // resolve method in super interfaces rather than class |
349 | String[] interfacesNames = type.getSuperInterfaceNames(); |
350 | if (interfacesNames != null) { |
351 | for (int i = 0, max = interfacesNames.length; i < max; i++) { |
352 | IApiTypeRoot classFile = Util.getClassFile( |
353 | new IApiComponent[] { sourceComponent }, |
354 | interfacesNames[i]); |
355 | IApiType superinterface = classFile.getStructure(); |
356 | if (superinterface != null && resolveVirtualMethod0(sourceComponent, superinterface, methodName, methodSignature)) { |
357 | return true; |
358 | } |
359 | } |
360 | } |
361 | break; |
362 | case IReference.REF_VIRTUALMETHOD : |
363 | case IReference.REF_SPECIALMETHOD : |
364 | String superclassName = type.getSuperclassName(); |
365 | if (superclassName != null) { |
366 | IApiTypeRoot classFile = Util.getClassFile( |
367 | new IApiComponent[] { sourceComponent }, |
368 | superclassName); |
369 | IApiType superclass = classFile.getStructure(); |
370 | boolean resolved = resolveVirtualMethod0(sourceComponent, superclass, methodName, methodSignature); |
371 | if (resolved) { |
372 | return resolved; |
373 | } |
374 | } |
375 | if (Flags.isAbstract(type.getModifiers())) { |
376 | interfacesNames = type.getSuperInterfaceNames(); |
377 | if (interfacesNames != null) { |
378 | for (int i = 0, max = interfacesNames.length; i < max; i++) { |
379 | IApiTypeRoot classFile = Util.getClassFile( |
380 | new IApiComponent[] { sourceComponent }, |
381 | interfacesNames[i]); |
382 | IApiType superinterface = classFile.getStructure(); |
383 | if (superinterface != null && resolveVirtualMethod0(sourceComponent, superinterface, methodName, methodSignature)) { |
384 | return true; |
385 | } |
386 | } |
387 | } |
388 | } |
389 | } |
390 | return false; |
391 | } |
392 | /** |
393 | * Used by the search engine when resolving multiple references. |
394 | * |
395 | * @param resolution resolved reference |
396 | */ |
397 | public void setResolution(IApiMember resolution) { |
398 | fResolved = resolution; |
399 | } |
400 | |
401 | /* (non-Javadoc) |
402 | * @see java.lang.Object#toString() |
403 | */ |
404 | public String toString() { |
405 | StringBuffer buf = new StringBuffer(); |
406 | buf.append("From: "); //$NON-NLS-1$ |
407 | IApiMember member = getMember(); |
408 | buf.append(member.getHandle().toString()); |
409 | if (getResolvedReference() == null) { |
410 | buf.append("\nUnresolved To: "); //$NON-NLS-1$ |
411 | buf.append(getReferencedTypeName()); |
412 | if (getReferencedMemberName() != null) { |
413 | buf.append('#'); |
414 | buf.append(getReferencedMemberName()); |
415 | } |
416 | if (getReferencedSignature() != null) { |
417 | buf.append('#'); |
418 | buf.append(getReferencedSignature()); |
419 | } |
420 | } else { |
421 | buf.append("\nResolved To: "); //$NON-NLS-1$ |
422 | buf.append(getResolvedReference().getHandle().toString()); |
423 | } |
424 | buf.append("\nKind: "); //$NON-NLS-1$ |
425 | buf.append(Reference.getReferenceText(getReferenceKind())); |
426 | return buf.toString(); |
427 | } |
428 | |
429 | public void setResolveStatus(boolean value) { |
430 | this.fStatus = value; |
431 | } |
432 | |
433 | /** |
434 | * Returns the string representation for the given reference kind or |
435 | * <code>UKNOWN_KIND</code> if the kind cannot be determined. |
436 | * |
437 | * @param kind the kid(s) to get the display text for |
438 | * @return the string for the reference kind |
439 | * @since 1.0.1 |
440 | */ |
441 | public static final String getReferenceText(int kind) { |
442 | StringBuffer buffer = new StringBuffer(); |
443 | if((kind & IReference.REF_EXTENDS) > 0) { |
444 | buffer.append("EXTENDS"); //$NON-NLS-1$ |
445 | } |
446 | if((kind & IReference.REF_IMPLEMENTS) > 0) { |
447 | if(buffer.length() != 0) { |
448 | buffer.append(" | "); //$NON-NLS-1$ |
449 | } |
450 | buffer.append("IMPLEMENTS"); //$NON-NLS-1$ |
451 | } |
452 | if ((kind & IReference.REF_SPECIALMETHOD) > 0) { |
453 | if(buffer.length() != 0) { |
454 | buffer.append(" | "); //$NON-NLS-1$ |
455 | } |
456 | buffer.append("INVOKED_SPECIAL"); //$NON-NLS-1$ |
457 | } |
458 | if((kind & IReference.REF_STATICMETHOD) > 0) { |
459 | if(buffer.length() != 0) { |
460 | buffer.append(" | "); //$NON-NLS-1$ |
461 | } |
462 | buffer.append("INVOKED_STATIC"); //$NON-NLS-1$ |
463 | } |
464 | if((kind & IReference.REF_PUTFIELD) > 0) { |
465 | if(buffer.length() != 0) { |
466 | buffer.append(" | "); //$NON-NLS-1$ |
467 | } |
468 | buffer.append("PUT_FIELD"); //$NON-NLS-1$ |
469 | } |
470 | if((kind & IReference.REF_PUTSTATIC) > 0) { |
471 | if(buffer.length() != 0) { |
472 | buffer.append(" | "); //$NON-NLS-1$ |
473 | } |
474 | buffer.append("PUT_STATIC_FIELD"); //$NON-NLS-1$ |
475 | } |
476 | if((kind & IReference.REF_FIELDDECL) > 0) { |
477 | if(buffer.length() != 0) { |
478 | buffer.append(" | "); //$NON-NLS-1$ |
479 | } |
480 | buffer.append("DECLARED_FIELD"); //$NON-NLS-1$ |
481 | } |
482 | if((kind & IReference.REF_PARAMETERIZED_TYPEDECL) > 0) { |
483 | if(buffer.length() != 0) { |
484 | buffer.append(" | "); //$NON-NLS-1$ |
485 | } |
486 | buffer.append("DECLARED_PARAMETERIZED_TYPE"); //$NON-NLS-1$ |
487 | } |
488 | if((kind & IReference.REF_PARAMETERIZED_FIELDDECL) > 0) { |
489 | if(buffer.length() != 0) { |
490 | buffer.append(" | "); //$NON-NLS-1$ |
491 | } |
492 | buffer.append("DECLARED_PARAMETERIZED_FIELD"); //$NON-NLS-1$ |
493 | } |
494 | if((kind & IReference.REF_PARAMETERIZED_METHODDECL) > 0) { |
495 | if(buffer.length() != 0) { |
496 | buffer.append(" | "); //$NON-NLS-1$ |
497 | } |
498 | buffer.append("DECLARED_PARAMETERIZED_METHOD"); //$NON-NLS-1$ |
499 | } |
500 | if((kind & IReference.REF_PARAMETER) > 0) { |
501 | if(buffer.length() != 0) { |
502 | buffer.append(" | "); //$NON-NLS-1$ |
503 | } |
504 | buffer.append("PARAMETER"); //$NON-NLS-1$ |
505 | } |
506 | if((kind & IReference.REF_LOCALVARIABLEDECL) > 0) { |
507 | if(buffer.length() != 0) { |
508 | buffer.append(" | "); //$NON-NLS-1$ |
509 | } |
510 | buffer.append("LOCAL_VAR_DECLARED"); //$NON-NLS-1$ |
511 | } |
512 | if((kind & IReference.REF_PARAMETERIZED_VARIABLE) > 0) { |
513 | if(buffer.length() != 0) { |
514 | buffer.append(" | "); //$NON-NLS-1$ |
515 | } |
516 | buffer.append("DECLARED_PARAMETERIZED_VARIABLE"); //$NON-NLS-1$ |
517 | } |
518 | if((kind & IReference.REF_THROWS) > 0) { |
519 | if(buffer.length() != 0) { |
520 | buffer.append(" | "); //$NON-NLS-1$ |
521 | } |
522 | buffer.append("THROWS"); //$NON-NLS-1$ |
523 | } |
524 | if((kind & IReference.REF_CHECKCAST) > 0) { |
525 | if(buffer.length() != 0) { |
526 | buffer.append(" | "); //$NON-NLS-1$ |
527 | } |
528 | buffer.append("CASTS"); //$NON-NLS-1$ |
529 | } |
530 | if((kind & IReference.REF_ARRAYALLOC) > 0) { |
531 | if(buffer.length() != 0) { |
532 | buffer.append(" | "); //$NON-NLS-1$ |
533 | } |
534 | buffer.append("ALLOCATES_ARRAY"); //$NON-NLS-1$ |
535 | } |
536 | if((kind & IReference.REF_CATCHEXCEPTION) > 0) { |
537 | if(buffer.length() != 0) { |
538 | buffer.append(" | "); //$NON-NLS-1$ |
539 | } |
540 | buffer.append("CATCHES_EXCEPTION"); //$NON-NLS-1$ |
541 | } |
542 | if((kind & IReference.REF_GETFIELD) > 0) { |
543 | if(buffer.length() != 0) { |
544 | buffer.append(" | "); //$NON-NLS-1$ |
545 | } |
546 | buffer.append("GETS_FIELD"); //$NON-NLS-1$ |
547 | } |
548 | if((kind & IReference.REF_GETSTATIC) > 0) { |
549 | if(buffer.length() != 0) { |
550 | buffer.append(" | "); //$NON-NLS-1$ |
551 | } |
552 | buffer.append("GETS_STATIC_FIELD"); //$NON-NLS-1$ |
553 | } |
554 | if((kind & IReference.REF_INSTANCEOF) > 0) { |
555 | if(buffer.length() != 0) { |
556 | buffer.append(" | "); //$NON-NLS-1$ |
557 | } |
558 | buffer.append("INSTANCEOF"); //$NON-NLS-1$ |
559 | } |
560 | if((kind & IReference.REF_INTERFACEMETHOD) > 0) { |
561 | if(buffer.length() != 0) { |
562 | buffer.append(" | "); //$NON-NLS-1$ |
563 | } |
564 | buffer.append("INTERFACE_METHOD"); //$NON-NLS-1$ |
565 | } |
566 | if((kind & IReference.REF_CONSTRUCTORMETHOD) > 0) { |
567 | if(buffer.length() != 0) { |
568 | buffer.append(" | "); //$NON-NLS-1$ |
569 | } |
570 | buffer.append("CONSTRUCTOR_METHOD"); //$NON-NLS-1$ |
571 | } |
572 | if((kind & IReference.REF_LOCALVARIABLE) > 0) { |
573 | if(buffer.length() != 0) { |
574 | buffer.append(" | "); //$NON-NLS-1$ |
575 | } |
576 | buffer.append("LOCAL_VARIABLE"); //$NON-NLS-1$ |
577 | } |
578 | if((kind & IReference.REF_PASSEDPARAMETER) > 0) { |
579 | if(buffer.length() != 0) { |
580 | buffer.append(" | "); //$NON-NLS-1$ |
581 | } |
582 | buffer.append("PASSED_PARAMETER"); //$NON-NLS-1$ |
583 | } |
584 | if((kind & IReference.REF_RETURNTYPE) > 0) { |
585 | if(buffer.length() != 0) { |
586 | buffer.append(" | "); //$NON-NLS-1$ |
587 | } |
588 | buffer.append("RETURN_TYPE"); //$NON-NLS-1$ |
589 | } |
590 | if((kind & IReference.REF_VIRTUALMETHOD) > 0) { |
591 | if(buffer.length() != 0) { |
592 | buffer.append(" | "); //$NON-NLS-1$ |
593 | } |
594 | buffer.append("VIRTUAL_METHOD"); //$NON-NLS-1$ |
595 | } |
596 | if((kind & IReference.REF_CONSTANTPOOL) > 0) { |
597 | if(buffer.length() != 0) { |
598 | buffer.append(" | "); //$NON-NLS-1$ |
599 | } |
600 | buffer.append("CONSTANT_POOL"); //$NON-NLS-1$ |
601 | } |
602 | if((kind & IReference.REF_INSTANTIATE) > 0) { |
603 | if(buffer.length() != 0) { |
604 | buffer.append(" | "); //$NON-NLS-1$ |
605 | } |
606 | buffer.append("INSTANTIATION"); //$NON-NLS-1$ |
607 | } |
608 | if((kind & IReference.REF_OVERRIDE) > 0) { |
609 | if(buffer.length() != 0) { |
610 | buffer.append(" | "); //$NON-NLS-1$ |
611 | } |
612 | buffer.append("OVERRIDE"); //$NON-NLS-1$ |
613 | } |
614 | if((kind & IReference.REF_SUPER_CONSTRUCTORMETHOD) > 0) { |
615 | if(buffer.length() != 0) { |
616 | buffer.append(" | "); //$NON-NLS-1$ |
617 | } |
618 | buffer.append("SUPER_CONSTRUCTORMETHOD"); //$NON-NLS-1$ |
619 | } |
620 | if(buffer.length() == 0) { |
621 | buffer.append(Util.UNKNOWN_KIND); |
622 | } |
623 | return buffer.toString(); |
624 | } |
625 | |
626 | /** |
627 | * Builds a reference descriptor from this reference or <code>null</code>. |
628 | * |
629 | * @return corresponding reference descriptor or <code>null</code> if unresolved |
630 | * @throws CoreException if unable to resolve visibility |
631 | */ |
632 | public IReferenceDescriptor getReferenceDescriptor() throws CoreException { |
633 | IApiMember res = getResolvedReference(); |
634 | if (res == null) { |
635 | return null; |
636 | } |
637 | IApiComponent rcomponent = res.getApiComponent(); |
638 | IApiDescription description = rcomponent.getApiDescription(); |
639 | IApiAnnotations annot = description.resolveAnnotations(getResolvedReference().getHandle()); |
640 | int visibility = -1; |
641 | IApiComponent mcomponent = getMember().getApiComponent(); |
642 | if(annot != null) { |
643 | visibility = annot.getVisibility(); |
644 | if(annot.getVisibility() == VisibilityModifiers.PRIVATE) { |
645 | IApiComponent host = mcomponent.getHost(); |
646 | if(host != null && host.getId().equals(rcomponent.getId())) { |
647 | visibility = UseReportConverter.FRAGMENT_PERMISSIBLE; |
648 | } |
649 | else { |
650 | IApiAccess access = description.resolveAccessLevel( |
651 | Factory.componentDescriptor(mcomponent.getId()), // component descriptors in API description are not version qualified |
652 | getResolvedReference().getHandle().getPackage()); |
653 | if(access != null && access.getAccessLevel() == IApiAccess.FRIEND) { |
654 | visibility = VisibilityModifiers.PRIVATE_PERMISSIBLE; |
655 | } |
656 | } |
657 | } |
658 | } |
659 | else { |
660 | //overflow for those references that cannot be resolved |
661 | visibility = VisibilityModifiers.ALL_VISIBILITIES; |
662 | } |
663 | return new ReferenceDescriptor( |
664 | (IComponentDescriptor)mcomponent.getHandle(), |
665 | getMember().getHandle(), |
666 | getLineNumber(), |
667 | (IComponentDescriptor)rcomponent.getHandle(), |
668 | res.getHandle(), |
669 | getReferenceKind(), visibility); |
670 | } |
671 | } |