Bug 300446 - Field references are not always resolved to the correct owning member
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/Reference.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/Reference.java
index 429ae87..8de86ba 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/Reference.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/Reference.java
@@ -21,6 +21,7 @@
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;
@@ -261,7 +262,7 @@
fResolved = type;
break;
case IReference.T_FIELD_REFERENCE:
- fResolved = type.getField(getReferencedMemberName());
+ resolveField(type, getReferencedMemberName());
break;
case IReference.T_METHOD_REFERENCE:
resolveVirtualMethod(type, getReferencedMemberName(), getReferencedSignature());
@@ -290,7 +291,7 @@
case IReference.T_TYPE_REFERENCE:
return true;
case IReference.T_FIELD_REFERENCE:
- return type.getField(getReferencedMemberName()) != null;
+ return resolveField(type, getReferencedMemberName());
case IReference.T_METHOD_REFERENCE:
return resolveVirtualMethod0(sourceComponent, type, getReferencedMemberName(), getReferencedSignature());
}
@@ -298,6 +299,26 @@
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.
@@ -424,6 +445,7 @@
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());
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceExtractor.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceExtractor.java
index 117eaf6..1fa4195 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceExtractor.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceExtractor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * Copyright (c) 2007, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -306,6 +306,9 @@
Reference reference = ReferenceExtractor.this.addFieldReference(Type.getObjectType(owner), name, refType);
if (reference != null) {
this.linePositionTracker.addLocation(reference);
+ if(refType == IReference.REF_GETFIELD || refType == IReference.REF_PUTFIELD) {
+ ReferenceExtractor.this.fieldtracker.addField(reference);
+ }
}
}
}
@@ -400,6 +403,9 @@
Reference reference = ReferenceExtractor.this.addMethodReference(declaringType, name, desc, kind);
if (reference != null) {
this.linePositionTracker.addLocation(reference);
+ if(kind == IReference.REF_STATICMETHOD) {
+ ReferenceExtractor.this.fieldtracker.addAccessor(reference);
+ }
}
}
this.stringLiteral = null;
@@ -573,7 +579,72 @@
}
-
+
+ /**
+ * @since 1.1
+ */
+ static class FieldTracker {
+ HashMap accessors = new HashMap();
+ ArrayList fields = new ArrayList();
+ ReferenceExtractor extractor = null;
+ /**
+ * Constructor
+ */
+ public FieldTracker(ReferenceExtractor extractor) {
+ this.extractor = extractor;
+ }
+
+ /**
+ * Add a field to be tracked
+ * @param field
+ */
+ public void addField(Reference ref) {
+ if(ref != null) {
+ fields.add(ref);
+ }
+ }
+ /**
+ * Add an accessor to be tracked
+ * @param accessor
+ */
+ public void addAccessor(Reference ref) {
+ if(ref != null) {
+ String key = ref.getReferencedMemberName();
+ List refs = (List) accessors.get(key);
+ if(refs == null) {
+ refs = new ArrayList();
+ accessors.put(key, refs);
+ }
+ refs.add(ref);
+ }
+
+ }
+ /**
+ * Resolve any synthetic field access to their accessor
+ */
+ public void resolveSyntheticFields() {
+ Reference accessor = null, field = null;
+ List refs = null;
+ for (int i = 0; i < fields.size(); i++) {
+ field = (Reference) fields.get(i);
+ refs = (List) accessors.get(field.getMember().getName());
+ if(refs != null) {
+ for (Iterator iter = refs.iterator(); iter.hasNext();) {
+ accessor = (Reference) iter.next();
+ Reference refer = Reference.fieldReference(accessor.getMember(),
+ field.getReferencedTypeName(),
+ field.getReferencedMemberName(),
+ field.getReferenceKind());
+ refer.setLineNumber(accessor.getLineNumber());
+ this.extractor.collector.add(refer);
+ }
+ //we resolved it, remove it
+ this.extractor.collector.remove(field);
+ }
+ }
+ }
+ }
+
static class LinePositionTracker {
List labelsAndLocations;
SortedSet lineInfos;
@@ -748,7 +819,7 @@
* The list we collect references in. Entries in the list are
* of the type {@link org.eclipse.pde.api.tools.internal.provisional.builder.IReference}
*/
- private Set collector = null;
+ Set collector = null;
/**
* The full internal name of the class we are extracting references from
@@ -758,7 +829,7 @@
/**
* Current type being visited.
*/
- private IApiType fType;
+ IApiType fType;
/**
* Stack of members being visited. When a member is entered its
@@ -789,6 +860,12 @@
* Bit mask of {@link ReferenceModifiers} to extract.
*/
private int fReferenceKinds = 0;
+
+ /**
+ * Track synthetic field / accessor
+ * @since 1.1
+ */
+ FieldTracker fieldtracker = null;
/**
* Bit mask that determines if we need to visit members
@@ -820,9 +897,26 @@
fType = type;
this.collector = collector;
fReferenceKinds = referenceKinds;
- fIsVisitMembers = (VISIT_MEMBERS_MASK & fReferenceKinds) > 0;
+ fIsVisitMembers = (VISIT_MEMBERS_MASK & fReferenceKinds) > 0;
+ fieldtracker = new FieldTracker(this);
}
+ /**
+ * Constructor
+ * @param type
+ * @param collector
+ * @param referenceKinds
+ * @param tracker
+ */
+ protected ReferenceExtractor(IApiType type, Set collector, int referenceKinds, FieldTracker tracker) {
+ super(new ClassNode());
+ fType = type;
+ this.collector = collector;
+ fReferenceKinds = referenceKinds;
+ fIsVisitMembers = (VISIT_MEMBERS_MASK & fReferenceKinds) > 0;
+ fieldtracker = tracker;
+ }
+
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -853,7 +947,7 @@
}
return !(this.classname.equals(owner) || this.classname.startsWith(owner) || "<clinit>".equals(owner) || "this".equals(owner)); //$NON-NLS-1$ //$NON-NLS-2$
}
-
+
/**
* Returns whether the specified reference should be
* considered when extracting references. Configured by setting on whether
@@ -863,7 +957,8 @@
* @return whether to include the reference
*/
protected boolean consider(Reference ref) {
- if ((ref.getReferenceKind() & fReferenceKinds) == 0) {
+ int kind = ref.getReferenceKind();
+ if ((kind & fReferenceKinds) == 0) {
return false;
}
if (this.fIncludeLocalRefs) {
@@ -871,7 +966,8 @@
}
// don't consider references to anonymous types or elements in them
String referencedTypeName = ref.getReferencedTypeName();
- if (ref.getReferenceKind() == IReference.REF_VIRTUALMETHOD || ref.getReferenceKind() == IReference.REF_OVERRIDE) {
+ if (kind == IReference.REF_VIRTUALMETHOD || kind == IReference.REF_OVERRIDE ||
+ kind == IReference.REF_GETFIELD || kind == IReference.REF_PUTFIELD) {
return true;
}
if (referencedTypeName.startsWith(fType.getName())) {
@@ -1075,6 +1171,9 @@
System.out.println("ending visit of type: ["+typeName+"]"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
+ if(!this.fType.isMemberType()) {
+ fieldtracker.resolveSyntheticFields();
+ }
}
/* (non-Javadoc)
@@ -1104,6 +1203,9 @@
this.addTypeReference(Type.getType(desc), IReference.REF_FIELDDECL);
}
}
+ else {
+ fieldtracker.addField(addTypeReference(Type.getType(desc), IReference.REF_FIELDDECL));
+ }
this.exitMember();
}
return null;
@@ -1157,7 +1259,7 @@
*/
private Set processInnerClass(IApiType type, int refkinds) throws CoreException {
HashSet refs = new HashSet();
- ReferenceExtractor extractor = new ReferenceExtractor(type, refs, refkinds);
+ ReferenceExtractor extractor = new ReferenceExtractor(type, refs, refkinds, this.fieldtracker);
ClassReader reader = new ClassReader(((AbstractApiTypeRoot)type.getTypeRoot()).getContents());
reader.accept(extractor, ClassReader.SKIP_FRAMES);
return refs;
@@ -1202,23 +1304,25 @@
Reference.methodReference(method, superTypeName, method.getName(), method.getSignature(), IReference.REF_OVERRIDE));
}
}
- if((access & Opcodes.ACC_SYNTHETIC) == 0 && !"<clinit>".equals(name)) { //$NON-NLS-1$
+ if(!"<clinit>".equals(name)) { //$NON-NLS-1$
int argumentcount = 0;
- if(signature != null) {
- this.processSignature(name, signature, IReference.REF_PARAMETERIZED_METHODDECL, METHOD);
- argumentcount = this.signaturevisitor.argumentcount;
- }
- else {
- Type[] arguments = Type.getArgumentTypes(desc);
- for(int i = 0; i < arguments.length; i++) {
- Type type = arguments[i];
- this.addTypeReference(type, IReference.REF_PARAMETER);
- argumentcount += type.getSize();
+ if((access & Opcodes.ACC_SYNTHETIC) == 0) {
+ if(signature != null) {
+ this.processSignature(name, signature, IReference.REF_PARAMETERIZED_METHODDECL, METHOD);
+ argumentcount = this.signaturevisitor.argumentcount;
}
- this.addTypeReference(Type.getReturnType(desc), IReference.REF_RETURNTYPE);
- if(exceptions != null) {
- for(int i = 0; i < exceptions.length; i++) {
- this.addTypeReference(Type.getObjectType(exceptions[i]), IReference.REF_THROWS);
+ else {
+ Type[] arguments = Type.getArgumentTypes(desc);
+ for(int i = 0; i < arguments.length; i++) {
+ Type type = arguments[i];
+ this.addTypeReference(type, IReference.REF_PARAMETER);
+ argumentcount += type.getSize();
+ }
+ this.addTypeReference(Type.getReturnType(desc), IReference.REF_RETURNTYPE);
+ if(exceptions != null) {
+ for(int i = 0; i < exceptions.length; i++) {
+ this.addTypeReference(Type.getObjectType(exceptions[i]), IReference.REF_THROWS);
+ }
}
}
}