summaryrefslogtreecommitdiffstats
path: root/org.aspectj.ajdt.core
diff options
context:
space:
mode:
authoraclement <aclement>2005-08-12 11:01:44 +0000
committeraclement <aclement>2005-08-12 11:01:44 +0000
commit7fd684f0621e8a8d0ed59b53f5abe2bd4331aa96 (patch)
treeee811f2ebb92fbb9b9aafb3deb5cd710f0abf2c9 /org.aspectj.ajdt.core
parentc840a149bfe03c51475f7c75611a6a037168baaf (diff)
downloadaspectj-7fd684f0621e8a8d0ed59b53f5abe2bd4331aa96.tar.gz
aspectj-7fd684f0621e8a8d0ed59b53f5abe2bd4331aa96.zip
genericitds: when the compiler asks for a member that is in fact from an ITD on a generic type, we fix up the field and return it parameterized for the particular type.
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java133
1 files changed, 123 insertions, 10 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java
index 068079b70..377ef20d7 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java
@@ -1,5 +1,5 @@
/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * Copyright (c) 2002,2005 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
@@ -8,6 +8,7 @@
*
* Contributors:
* PARC initial implementation
+ * Andy Clement - upgrade to support fields targetting generic types
* ******************************************************************/
@@ -15,47 +16,158 @@ package org.aspectj.ajdt.internal.compiler.lookup;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.IMemberFinder;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.weaver.NewFieldTypeMunger;
+/**
+ * The member finder looks after intertype declared members on a type, there is
+ * one member finder per type that was hit by an ITD.
+ */
public class InterTypeMemberFinder implements IMemberFinder {
private List interTypeFields = new ArrayList();
+ private Map /* intertypefield > NewFieldTypeMunger */ interTypeFieldMungers = new HashMap();
private List interTypeMethods = new ArrayList();
public SourceTypeBinding sourceTypeBinding;
- public FieldBinding getField(
- SourceTypeBinding sourceTypeBinding,
- char[] fieldName,
- InvocationSite site,
- Scope scope)
- {
+ public FieldBinding getField(SourceTypeBinding sourceTypeBinding,char[] fieldName,InvocationSite site,Scope scope) {
FieldBinding retField = sourceTypeBinding.getFieldBase(fieldName, true); // XXX may need to get the correct value for second parameter in the future (see #55341)
if (interTypeFields.isEmpty()) return retField;
int fieldLength = fieldName.length;
for (int i=0, len=interTypeFields.size(); i < len; i++) {
FieldBinding field = (FieldBinding)interTypeFields.get(i);
- if (field.name.length == fieldLength && CharOperation.prefixEquals(field.name, fieldName)) {
+ if (field.name.length == fieldLength && CharOperation.prefixEquals(field.name, fieldName)) {
retField = resolveConflicts(sourceTypeBinding, retField, field, site, scope);
+
+ // If the intertype field was declared upon a generic type, it is here that we need
+ // to fix up the field we have and return a ParameterizedFieldBinding which has been
+ // parameterized such that it matches the chosen parameterization of the generic type
+ // that is asking for the field (clear?).
+ retField = fixAnyParameterization(site,retField,sourceTypeBinding);
}
}
return retField;
}
+ /**
+ * Modifies a field if required to fix up its type parameters such that they refer to real type
+ * variables in the target generic type. This method exits fast if it determines there is
+ * nothing to do.
+ */
+ private FieldBinding fixAnyParameterization(InvocationSite site,FieldBinding field, SourceTypeBinding sourceTypeBinding) {
+
+ // Nothing to do if its not targetting a parameterized type
+ if (!(field.type instanceof ParameterizedTypeBinding) ||
+ (field.type instanceof RawTypeBinding)) return field; // In eclipse world raw is a subclass of parameterized, doh!
+
+ if (!(site instanceof QualifiedNameReference)) return field;
+
+ NewFieldTypeMunger nfMunger = (NewFieldTypeMunger)interTypeFieldMungers.get(field);
+
+ if (!nfMunger.hasGenericTypeVariableMap()) return field;
+
+ TypeBinding bindingAtInvocationSite = ((LocalVariableBinding)((QualifiedNameReference)site).binding).type;
+
+ ParameterizedTypeBinding pBinding = null;
+
+ if (bindingAtInvocationSite instanceof ParameterizedTypeBinding) {
+ pBinding = (ParameterizedTypeBinding)bindingAtInvocationSite;
+ } else if (bindingAtInvocationSite instanceof SourceTypeBinding) {
+ pBinding = (ParameterizedTypeBinding)discoverCorrectBinding(bindingAtInvocationSite,((InterTypeFieldBinding)field).targetType);
+ }
+
+ if (pBinding.arguments == null) return field;
+ // 1. go through it looking for single type references whose names match type parameters
+ // 2. for any you find, you need to replace it with a type variable binding for the matcing thing in the
+ // parameterized instance that is being used.
+
+ // IF we start reporting error messages with the wrong letter when reporting information about the ITD, we might need a subtype of
+ // typevariablebinding that knows the alternative name for the variable (i.e. the letter that was used in the ITD...)
+ patchUp(field.type,nfMunger);
+
+ return new ParameterizedInterTypeFieldBinding(pBinding,field);
+ }
+
+ private ReferenceBinding discoverCorrectBinding(TypeBinding tBinding,ReferenceBinding binding) {
+ if (tBinding instanceof ParameterizedTypeBinding) {
+ ParameterizedTypeBinding ptBinding = (ParameterizedTypeBinding)tBinding;
+ if (ptBinding.type.equals(binding)) {
+ return ptBinding;
+ }
+ }
+ ReferenceBinding superclassBinding = null;
+ ReferenceBinding[] superinterfaceBindings = null;
+ if (tBinding instanceof SourceTypeBinding) {
+ SourceTypeBinding stBinding = (SourceTypeBinding)tBinding;
+ superclassBinding = stBinding.superclass();
+ superinterfaceBindings = stBinding.superInterfaces();
+ } else if (tBinding instanceof BinaryTypeBinding) {
+ BinaryTypeBinding stBinding = (BinaryTypeBinding)tBinding;
+ superclassBinding = stBinding.superclass();
+ superinterfaceBindings = stBinding.superInterfaces();
+ }
+ if (superclassBinding!=null) {
+ ReferenceBinding foundit = discoverCorrectBinding(superclassBinding,binding);
+ if (foundit!=null) return foundit;
+ }
+ if (superinterfaceBindings!=null) {
+ for (int i = 0; i < superinterfaceBindings.length; i++) {
+ ReferenceBinding binding2 = superinterfaceBindings[i];
+ ReferenceBinding foundit2 = discoverCorrectBinding(binding2,binding);
+ if (foundit2!=null) return foundit2;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Recurses over a type binding, looking for type variable bindings and replacing these 'placeholder' ones
+ * with references to the real type variables for the generic type.
+ *
+ * FIXME asc - can do this just once when the field is first added to the member finder and then keep it around? surely?
+ */
+ private void patchUp(TypeBinding typeBinding,NewFieldTypeMunger nfMunger) {
+ if (!(typeBinding instanceof ParameterizedTypeBinding)) return;
+ TypeBinding [] args = ((ParameterizedTypeBinding)typeBinding).arguments;
+ if (args!=null) {
+ for (int i = 0; i < args.length; i++) {
+ TypeBinding binding = args[i];
+ if (binding instanceof TypeVariableBinding) {
+ int replacement = nfMunger.getGenericTypeVariableIndexFor(CharOperation.charToString(((TypeVariableBinding)binding).sourceName));
+ if (replacement!=-1) {
+ ((ParameterizedTypeBinding)typeBinding).arguments[i] = sourceTypeBinding.typeVariables()[replacement];
+ }
+ } else if (binding instanceof ParameterizedTypeBinding) {
+ patchUp(binding,nfMunger);
+ }
+ }
+ }
+ }
+
+
private FieldBinding resolveConflicts(
SourceTypeBinding sourceTypeBinding,
FieldBinding retField,
@@ -383,9 +495,10 @@ public class InterTypeMemberFinder implements IMemberFinder {
- public void addInterTypeField(FieldBinding binding) {
+ public void addInterTypeField(FieldBinding binding, NewFieldTypeMunger munger) {
//System.err.println("adding: " + binding + " to " + this);
interTypeFields.add(binding);
+ interTypeFieldMungers.put(binding,munger);
}
public void addInterTypeMethod(MethodBinding binding) {