blob: 3ba725f0eaddd1f9140a26b581b271576834df3e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.api.tools.internal.builder;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.pde.api.tools.internal.model.StubApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.provisional.IApiAccess;
import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiField;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;
import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
import org.eclipse.pde.api.tools.internal.search.IReferenceDescriptor;
import org.eclipse.pde.api.tools.internal.search.UseReportConverter;
import org.eclipse.pde.api.tools.internal.util.Signatures;
import org.eclipse.pde.api.tools.internal.util.Util;
/**
* Implementation of a reference from one member to another.
*
* @since 1.0.0
*/
public class Reference implements IReference {
/**
* Line number where the reference occurred.
*/
private int fSourceLine = -1;
/**
* Member where the reference occurred.
*/
private IApiMember fSourceMember;
/**
* One of the valid reference kinds
*
* @see IReference
*/
private int fKind = 0;
/**
* Flags for the reference
*/
private int fFlags = 0;
/**
* One of the valid type, method, field.
*/
private int fType;
/**
* Name of the referenced type
*/
private String fTypeName;
/**
* Name of the referenced member or <code>null</code>
*/
private String fMemberName;
/**
* Signature of the referenced method or <code>null</code>
*/
private String fSignature;
/**
* Resolved reference or <code>null</code>
*/
private IApiMember fResolved;
/**
* Resolvable status
*/
private boolean fStatus = true;
/**
* List of problems that have been reported against this problem
*/
private List<IApiProblem> fProblems = null;
/**
* Adds the given collection of
* {@link org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem}
* s to the backing listing.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type where virtual method lookup
* begins
* @param methodName name of the referenced method
* @param signature signature of the referenced method
* @param kind kind of method reference
*/
public boolean addProblems(IApiProblem problem) {
if (problem == null) {
return false;
}
if (fProblems == null) {
fProblems = new ArrayList<>(2);
}
if (fProblems.contains(problem)) {
return false;
}
return fProblems.add(problem);
}
/**
* Creates and returns a method reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type where virtual method lookup
* begins
* @param methodName name of the referenced method
* @param signature signature of the referenced method
* @param kind kind of method reference
*/
public static Reference methodReference(IApiMember origin, String typeName, String methodName, String signature, int kind) {
return methodReference(origin, typeName, methodName, signature, kind, 0);
}
/**
* Creates and returns a method reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type where virtual method lookup
* begins
* @param methodName name of the referenced method
* @param signature signature of the referenced method
* @param kind kind of method reference
* @param flags flags for the reference
* @since 1.0.600
*/
public static Reference methodReference(IApiMember origin, String typeName, String methodName, String signature, int kind, int flags) {
Reference ref = new Reference();
ref.fSourceMember = origin;
ref.fTypeName = typeName;
ref.fMemberName = methodName;
ref.fSignature = signature;
ref.fKind = kind;
ref.fType = IReference.T_METHOD_REFERENCE;
ref.fFlags = flags;
return ref;
}
/**
* Creates and returns a field reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type where field lookup begins
* @param fieldName name of the referenced field
* @param kind kind of field reference
*/
public static Reference fieldReference(IApiMember origin, String typeName, String fieldName, int kind) {
return fieldReference(origin, typeName, fieldName, kind, 0);
}
/**
* Creates and returns a field reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type where field lookup begins
* @param fieldName name of the referenced field
* @param kind kind of field reference
* @param flags flags for the reference
*
* @since 1.0.600
*/
public static Reference fieldReference(IApiMember origin, String typeName, String fieldName, int kind, int flags) {
Reference ref = new Reference();
ref.fSourceMember = origin;
ref.fTypeName = typeName;
ref.fMemberName = fieldName;
ref.fKind = kind;
ref.fType = IReference.T_FIELD_REFERENCE;
ref.fFlags = flags;
return ref;
}
/**
* Creates and returns a type reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type
* @param kind kind of reference
*/
public static Reference typeReference(IApiMember origin, String typeName, int kind) {
return typeReference(origin, typeName, null, kind, 0);
}
/**
* Creates and returns a type reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type
* @param signature extra type signature information
* @param kind kind of reference
*/
public static Reference typeReference(IApiMember origin, String typeName, String signature, int kind) {
return typeReference(origin, typeName, signature, kind, 0);
}
/**
* Creates and returns a type reference.
*
* @param origin where the reference occurred from
* @param typeName name of the referenced type
* @param signature extra type signature information
* @param kind kind of reference
* @param flags flags for the reference
*
* @since 1.0.600
*/
public static Reference typeReference(IApiMember origin, String typeName, String signature, int kind, int flags) {
Reference ref = new Reference();
ref.fSourceMember = origin;
ref.fTypeName = typeName;
ref.fKind = kind;
ref.fType = IReference.T_TYPE_REFERENCE;
ref.fSignature = signature;
ref.fFlags = flags;
return ref;
}
@Override
public int getLineNumber() {
return fSourceLine;
}
@Override
public IApiMember getMember() {
return fSourceMember;
}
@Override
public int getReferenceKind() {
return fKind;
}
@Override
public int getReferenceFlags() {
return fFlags;
}
/**
* OR's the given set of new flags with the current set of flags
*
* @param newflags
*/
public void setFlags(int newflags) {
fFlags |= newflags;
}
@Override
public int getReferenceType() {
return fType;
}
@Override
public IApiMember getResolvedReference() {
return fResolved;
}
@Override
public String getReferencedMemberName() {
return fMemberName;
}
@Override
public String getReferencedSignature() {
return fSignature;
}
@Override
public String getReferencedTypeName() {
return fTypeName;
}
/**
* Sets the line number - used by the reference extractor.
*
* @param line line number
*/
void setLineNumber(int line) {
fSourceLine = line;
}
/**
* Resolves this reference
*
* @throws CoreException
*/
public void resolve() throws CoreException {
if (!this.fStatus) {
return;
}
if (fResolved == null) {
IApiComponent sourceComponent = getMember().getApiComponent();
if (sourceComponent != null) {
IApiTypeRoot result = Util.getClassFile(sourceComponent.getBaseline().resolvePackage(sourceComponent, Signatures.getPackageName(getReferencedTypeName())), getReferencedTypeName());
if (result != null) {
IApiType type = result.getStructure();
if (type == null) {
// cannot resolve a type that is in a bad classfile
return;
}
switch (getReferenceType()) {
case IReference.T_TYPE_REFERENCE:
fResolved = type;
break;
case IReference.T_FIELD_REFERENCE:
resolveField(type, getReferencedMemberName());
break;
case IReference.T_METHOD_REFERENCE:
resolveVirtualMethod(type, getReferencedMemberName(), getReferencedSignature());
break;
default:
break;
}
}
}
}
}
public boolean resolve(int eeValue) throws CoreException {
IApiComponent sourceComponent = StubApiComponent.getStubApiComponent(eeValue);
if (sourceComponent == null) {
// if there is no source component for the EE value, the reference
// is considered as resolved
return true;
}
IApiTypeRoot result = Util.getClassFile(new IApiComponent[] { sourceComponent }, getReferencedTypeName());
if (result != null) {
IApiType type = result.getStructure();
if (type == null) {
return false;
}
switch (getReferenceType()) {
case IReference.T_TYPE_REFERENCE:
return true;
case IReference.T_FIELD_REFERENCE:
return resolveField(type, getReferencedMemberName());
case IReference.T_METHOD_REFERENCE:
return resolveMethod(sourceComponent, type, getReferencedMemberName(), getReferencedSignature());
default:
break;
}
}
return false;
}
/**
* Resolves the field in the parent class hierarchy
*
* @param type the initial type to search
* @param fieldame the name of the field
* @return true if the field resolved
* @throws CoreException
* @since 1.1
*/
private boolean resolveField(IApiType type, String fieldame) throws CoreException {
IApiField field = type.getField(fieldame);
if (field != null) {
fResolved = field;
return true;
}
IApiType superT = type.getSuperclass();
if (superT != null) {
return resolveField(superT, fieldame);
}
return false;
}
/**
* Resolves a virtual method and returns whether the method lookup was
* successful. We need to resolve the actual type that implements the method
* - i.e. do the virtual method lookup.
*
* @param callSiteComponent the component where the method call site was
* located
* @param typeName referenced type name
* @param methodName referenced method name
* @param methodSignature referenced method signature
* @returns whether the lookup succeeded
* @throws CoreException if something goes terribly wrong
*/
private boolean resolveVirtualMethod(IApiType type, String methodName, String methodSignature) throws CoreException {
if (setResolvedMethod(type.getMethod(methodName, methodSignature))) {
return true;
}
if (getReferenceKind() == IReference.REF_INTERFACEMETHOD) {
if (resolveInterfaceMethod(type, methodName, methodSignature)) {
return true;
}
} else if (resolveSuperTypeMethod(type, methodName, methodSignature)) {
return true;
}
if ((fFlags & F_DEFAULT_METHOD) > 0) {
return resolveInterfaceMethod(type, methodName, methodSignature);
}
return false;
}
/**
* Sets the resolved value for the invokevirtual or invokeinterface
* reference. If the method is not null and successfully updates the
* reference true is returned
*
* @param method
* @return
* @throws CoreException
* @since 1.0.600
*/
boolean setResolvedMethod(IApiMethod method) throws CoreException {
if (method != null) {
if (method.isSynthetic()) {
// don't resolve references to synthetic methods
return false;
} else {
if (method.isDefaultMethod()) {
// correct the referenced class sig
fTypeName = method.getEnclosingType().getName();
}
fResolved = method;
return true;
}
}
return false;
}
/**
* Resolves a given method in the super type hierarchy, returns true if it
* is resolved
*
* @param type
* @param methodName
* @param methodSignature
* @return
* @throws CoreException
* @since 1.0.600
*/
boolean resolveSuperTypeMethod(IApiType type, String methodName, String methodSignature) throws CoreException {
if (setResolvedMethod(type.getMethod(methodName, methodSignature))) {
return true;
}
IApiType superT = type.getSuperclass();
if (superT != null) {
return resolveVirtualMethod(superT, methodName, methodSignature);
}
return false;
}
/**
* Try to find the method in the interface hierarchy
*
* @param type
* @param methodName
* @param methodSignature
* @return
* @throws CoreException
*
* @since 1.0.600
*/
boolean resolveInterfaceMethod(IApiType type, String methodName, String methodSignature) throws CoreException {
if (setResolvedMethod(type.getMethod(methodName, methodSignature))) {
return true;
}
IApiType[] interfaces = type.getSuperInterfaces();
if (interfaces != null) {
for (IApiType i : interfaces) {
if(resolveInterfaceMethod(i, methodName, methodSignature)) {
return true;
}
}
}
return false;
}
/**
* Resolves a method and returns whether the method lookup was successful.
* We need to resolve the actual type that implements the method - i.e. do
* the virtual method lookup.
*
* @param callSiteComponent the component where the method call site was
* located
* @param typeName referenced type name
* @param methodName referenced method name
* @param methodSignature referenced method signature
* @returns whether the lookup succeeded
* @throws CoreException if something goes terribly wrong
*/
private boolean resolveMethod(IApiComponent sourceComponent, IApiType type, String methodName, String methodSignature) throws CoreException {
IApiMethod target = type.getMethod(methodName, methodSignature);
if (target != null) {
if (target.isSynthetic()) {
// don't resolve references to synthetic methods
return false;
} else {
return true;
}
}
switch (this.fKind) {
case IReference.REF_INTERFACEMETHOD:
// resolve method in super interfaces rather than class
String[] interfacesNames = type.getSuperInterfaceNames();
if (interfacesNames != null) {
for (String interfacesName : interfacesNames) {
IApiTypeRoot classFile = Util.getClassFile(new IApiComponent[] { sourceComponent }, interfacesName);
if (classFile == null) {
ApiPlugin.logErrorMessage("Class file for " + interfacesName + " was not found for " + sourceComponent.getName()); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
IApiType superinterface = classFile.getStructure();
if (superinterface != null && resolveMethod(sourceComponent, superinterface, methodName, methodSignature)) {
return true;
}
}
}
break;
case IReference.REF_STATICMETHOD:
String superclassName = type.getSuperclassName();
if (superclassName != null) {
IApiTypeRoot classFile = Util.getClassFile(new IApiComponent[] { sourceComponent }, superclassName);
if (classFile == null) {
ApiPlugin.logErrorMessage("Class file for " + superclassName + " was not found for " + sourceComponent.getName()); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
IApiType superclass = classFile.getStructure();
boolean resolved = resolveMethod(sourceComponent, superclass, methodName, methodSignature);
if (resolved) {
return resolved;
}
}
break;
case IReference.REF_VIRTUALMETHOD:
case IReference.REF_SPECIALMETHOD:
// check polymorphic methods: polymorphic method signature is
// ([Ljava/lang/Object;)Ljava/lang/Object;
target = type.getMethod(methodName, "([Ljava/lang/Object;)Ljava/lang/Object;"); //$NON-NLS-1$
if (target != null) {
if (methodName.equals(target.getName()) && target.isPolymorphic()) {
return true;
}
}
superclassName = type.getSuperclassName();
if (superclassName != null) {
IApiTypeRoot classFile = Util.getClassFile(new IApiComponent[] { sourceComponent }, superclassName);
if (classFile == null) {
ApiPlugin.logErrorMessage("Class file for " + superclassName + " was not found for " + sourceComponent.getName()); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
IApiType superclass = classFile.getStructure();
boolean resolved = resolveMethod(sourceComponent, superclass, methodName, methodSignature);
if (resolved) {
return resolved;
}
}
if (Flags.isAbstract(type.getModifiers())) {
interfacesNames = type.getSuperInterfaceNames();
if (interfacesNames != null) {
for (String interfacesName : interfacesNames) {
IApiTypeRoot classFile = Util.getClassFile(new IApiComponent[] { sourceComponent }, interfacesName);
if (classFile == null) {
ApiPlugin.logErrorMessage("Class file for " + interfacesName + " was not found for " + sourceComponent.getName()); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
IApiType superinterface = classFile.getStructure();
if (superinterface != null && resolveMethod(sourceComponent, superinterface, methodName, methodSignature)) {
return true;
}
}
}
}
break;
default:
break;
}
return false;
}
/**
* Used by the search engine when resolving multiple references.
*
* @param resolution resolved reference
*/
public void setResolution(IApiMember resolution) {
fResolved = resolution;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("From: "); //$NON-NLS-1$
IApiMember member = getMember();
buf.append(member.getHandle().toString());
buf.append(" [line: ").append(getLineNumber()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
if (getResolvedReference() == null) {
buf.append("\nUnresolved To: "); //$NON-NLS-1$
buf.append(getReferencedTypeName());
if (getReferencedMemberName() != null) {
buf.append('#');
buf.append(getReferencedMemberName());
}
if (getReferencedSignature() != null) {
buf.append('#');
buf.append(getReferencedSignature());
}
} else {
buf.append("\nResolved To: "); //$NON-NLS-1$
buf.append(getResolvedReference().getHandle().toString());
}
buf.append("\nKind: "); //$NON-NLS-1$
buf.append(Reference.getReferenceText(getReferenceKind()));
return buf.toString();
}
public void setResolveStatus(boolean value) {
this.fStatus = value;
}
/**
* Returns the string representation for the given reference kind or
* <code>UKNOWN_KIND</code> if the kind cannot be determined.
*
* @param kind the kid(s) to get the display text for
* @return the string for the reference kind
* @since 1.0.1
*/
public static final String getReferenceText(int kind) {
StringBuilder buffer = new StringBuilder();
if ((kind & IReference.REF_EXTENDS) > 0) {
buffer.append("EXTENDS"); //$NON-NLS-1$
}
if ((kind & IReference.REF_IMPLEMENTS) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("IMPLEMENTS"); //$NON-NLS-1$
}
if ((kind & IReference.REF_SPECIALMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("INVOKED_SPECIAL"); //$NON-NLS-1$
}
if ((kind & IReference.REF_STATICMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("INVOKED_STATIC"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PUTFIELD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("PUT_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PUTSTATIC) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("PUT_STATIC_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_FIELDDECL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("DECLARED_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PARAMETERIZED_TYPEDECL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("DECLARED_PARAMETERIZED_TYPE"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PARAMETERIZED_FIELDDECL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("DECLARED_PARAMETERIZED_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PARAMETERIZED_METHODDECL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("DECLARED_PARAMETERIZED_METHOD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PARAMETER) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("PARAMETER"); //$NON-NLS-1$
}
if ((kind & IReference.REF_LOCALVARIABLEDECL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("LOCAL_VAR_DECLARED"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PARAMETERIZED_VARIABLE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("DECLARED_PARAMETERIZED_VARIABLE"); //$NON-NLS-1$
}
if ((kind & IReference.REF_THROWS) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("THROWS"); //$NON-NLS-1$
}
if ((kind & IReference.REF_CHECKCAST) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("CASTS"); //$NON-NLS-1$
}
if ((kind & IReference.REF_ARRAYALLOC) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("ALLOCATES_ARRAY"); //$NON-NLS-1$
}
if ((kind & IReference.REF_CATCHEXCEPTION) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("CATCHES_EXCEPTION"); //$NON-NLS-1$
}
if ((kind & IReference.REF_GETFIELD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("GETS_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_GETSTATIC) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("GETS_STATIC_FIELD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_INSTANCEOF) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("INSTANCEOF"); //$NON-NLS-1$
}
if ((kind & IReference.REF_INTERFACEMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("INTERFACE_METHOD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_CONSTRUCTORMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("CONSTRUCTOR_METHOD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_LOCALVARIABLE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("LOCAL_VARIABLE"); //$NON-NLS-1$
}
if ((kind & IReference.REF_PASSEDPARAMETER) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("PASSED_PARAMETER"); //$NON-NLS-1$
}
if ((kind & IReference.REF_RETURNTYPE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("RETURN_TYPE"); //$NON-NLS-1$
}
if ((kind & IReference.REF_VIRTUALMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("VIRTUAL_METHOD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_CONSTANTPOOL) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("CONSTANT_POOL"); //$NON-NLS-1$
}
if ((kind & IReference.REF_INSTANTIATE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("INSTANTIATION"); //$NON-NLS-1$
}
if ((kind & IReference.REF_OVERRIDE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("OVERRIDE"); //$NON-NLS-1$
}
if ((kind & IReference.REF_SUPER_CONSTRUCTORMETHOD) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("SUPER_CONSTRUCTORMETHOD"); //$NON-NLS-1$
}
if ((kind & IReference.REF_ANNOTATION_USE) > 0) {
if (buffer.length() != 0) {
buffer.append(" | "); //$NON-NLS-1$
}
buffer.append("ANNOTATION_USE"); //$NON-NLS-1$
}
if (buffer.length() == 0) {
buffer.append(Util.UNKNOWN_KIND);
}
return buffer.toString();
}
/**
* Builds a reference descriptor from this reference or <code>null</code>.
*
* @return corresponding reference descriptor or <code>null</code> if
* unresolved
* @throws CoreException if unable to resolve visibility
*/
public IReferenceDescriptor getReferenceDescriptor() throws CoreException {
IApiMember res = getResolvedReference();
if (res == null) {
return null;
}
IApiComponent rcomponent = res.getApiComponent();
IApiDescription description = rcomponent.getApiDescription();
IApiAnnotations annot = description.resolveAnnotations(getResolvedReference().getHandle());
int visibility = -1;
IApiComponent mcomponent = getMember().getApiComponent();
if (annot != null) {
visibility = annot.getVisibility();
if (annot.getVisibility() == VisibilityModifiers.PRIVATE) {
IApiComponent host = mcomponent.getHost();
if (host != null && host.getSymbolicName().equals(rcomponent.getSymbolicName())) {
visibility = UseReportConverter.FRAGMENT_PERMISSIBLE;
} else {
IApiAccess access = description.resolveAccessLevel(Factory.componentDescriptor(mcomponent.getSymbolicName()),
getResolvedReference().getHandle().getPackage());
if (access != null && access.getAccessLevel() == IApiAccess.FRIEND) {
visibility = VisibilityModifiers.PRIVATE_PERMISSIBLE;
}
}
}
} else {
// overflow for those references that cannot be resolved
visibility = VisibilityModifiers.ALL_VISIBILITIES;
}
String[] messages = null;
if (fProblems != null) {
messages = new String[fProblems.size()];
for (int i = 0; i < messages.length; i++) {
messages[i] = fProblems.get(i).getMessage();
}
}
return Factory.referenceDescriptor((IComponentDescriptor) mcomponent.getHandle(), getMember().getHandle(), getLineNumber(), (IComponentDescriptor) rcomponent.getHandle(), res.getHandle(), getReferenceKind(), getReferenceFlags(), visibility, messages);
}
}