summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java48
-rw-r--r--tests/java5/generics/ITDReturningParameterizedType.aj2
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java2
-rw-r--r--weaver/src/org/aspectj/weaver/TypeX.java115
-rw-r--r--weaver/src/org/aspectj/weaver/World.java14
-rw-r--r--weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java15
6 files changed, 180 insertions, 16 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
index 5aeedd62e..931c7db15 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
@@ -47,11 +47,13 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
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.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.lookup.WildcardBinding;
/**
* @author Jim Hugunin
@@ -165,6 +167,19 @@ public class EclipseFactory {
TypeVariableBinding tvb = (TypeVariableBinding) binding;
return TypeX.forName(getName(tvb.firstBound)); // XXX needs more investigation as to whether this is correct in all cases
}
+ if (binding instanceof ParameterizedTypeBinding) {
+ ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) binding;
+ String[] arguments = new String[ptb.arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ if (ptb.arguments[i] instanceof WildcardBinding) {
+ WildcardBinding wcb = (WildcardBinding) ptb.arguments[i];
+ arguments[i] = getName(((TypeVariableBinding)wcb.typeVariable()).firstBound);
+ } else {
+ arguments[i] = getName(ptb.arguments[i]);
+ }
+ }
+ return TypeX.forParameterizedTypeNames(getName(binding), arguments);
+ }
return TypeX.forName(getName(binding));
}
@@ -307,21 +322,32 @@ public class EclipseFactory {
typeX = typeX.getComponentType();
}
return lookupEnvironment.createArrayType(makeTypeBinding(typeX), dim);
+ } else if (typeX.isParameterized()){
+ TypeX[] typeParameters = typeX.getTypeParameters();
+ ReferenceBinding baseTypeBinding = lookupBinding(typeX.getBaseName());
+ ReferenceBinding[] argumentBindings = new ReferenceBinding[typeParameters.length];
+ for (int i = 0; i < argumentBindings.length; i++) {
+ argumentBindings[i] = lookupBinding(typeParameters[i].getName());
+ }
+ ParameterizedTypeBinding ptb =
+ lookupEnvironment.createParameterizedType(baseTypeBinding,argumentBindings,baseTypeBinding.enclosingType());
+ return ptb;
} else {
- String n = typeX.getName();
- char[][] name = CharOperation.splitOn('.', n.toCharArray());
- ReferenceBinding rb = lookupEnvironment.getType(name);
- // XXX We do this because the pertypewithin aspectOf(Class) generated method needs it. Without this
- // we don't get a 'rawtype' as the argument type for a messagesend to aspectOf() and this leads to
- // a compile error if some client class calls aspectOf(A.class) or similar as it says Class<A> isn't
- // compatible with Class<T>
- if (n.equals("java.lang.Class"))
- rb = lookupEnvironment.createRawType(rb,rb.enclosingType());
- return rb;
+ return lookupBinding(typeX.getName());
}
}
-
+ private ReferenceBinding lookupBinding(String sname) {
+ char[][] name = CharOperation.splitOn('.', sname.toCharArray());
+ ReferenceBinding rb = lookupEnvironment.getType(name);
+ // XXX We do this because the pertypewithin aspectOf(Class) generated method needs it. Without this
+ // we don't get a 'rawtype' as the argument type for a messagesend to aspectOf() and this leads to
+ // a compile error if some client class calls aspectOf(A.class) or similar as it says Class<A> isn't
+ // compatible with Class<T>
+ if (sname.equals("java.lang.Class"))
+ rb = lookupEnvironment.createRawType(rb,rb.enclosingType());
+ return rb;
+ }
public TypeBinding[] makeTypeBindings(TypeX[] types) {
int len = types.length;
diff --git a/tests/java5/generics/ITDReturningParameterizedType.aj b/tests/java5/generics/ITDReturningParameterizedType.aj
index aa5f3e978..4495e8042 100644
--- a/tests/java5/generics/ITDReturningParameterizedType.aj
+++ b/tests/java5/generics/ITDReturningParameterizedType.aj
@@ -2,6 +2,8 @@ import java.util.*;
public aspect ITDReturningParameterizedType {
+ private List<String> myStrings = new ArrayList<String>();
+
private List<String> C.strings = new ArrayList<String>();
public List<String> C.getStrings() {
diff --git a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java
index 52e285c83..1f0ad25f9 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java
+++ b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java
@@ -42,7 +42,7 @@ public class AllTestsAspectJ150 {
suite.addTest(SuppressedWarnings.suite());
suite.addTest(DeclareAnnotationTests.suite());
-
+ suite.addTest(GenericsTests.suite());
suite.addTest(AtAjSyntaxTests.suite());
//$JUnit-END$
return suite;
diff --git a/weaver/src/org/aspectj/weaver/TypeX.java b/weaver/src/org/aspectj/weaver/TypeX.java
index 2b046a370..cd9e352f3 100644
--- a/weaver/src/org/aspectj/weaver/TypeX.java
+++ b/weaver/src/org/aspectj/weaver/TypeX.java
@@ -23,6 +23,11 @@ public class TypeX implements AnnotatedElement {
* This is the bytecode string representation of this Type
*/
protected String signature;
+
+ /**
+ * If this is a parameterized type, these are its parameters
+ */
+ protected TypeX[] typeParameters;
/**
* @param signature the bytecode string representation of this Type
@@ -101,7 +106,29 @@ public class TypeX implements AnnotatedElement {
}
return ret;
}
-
+
+ /**
+ * Makes a parameterized type with the given name
+ * and parameterized type names.
+ */
+ public static TypeX forParameterizedTypeNames(String name, String[] paramTypeNames) {
+ TypeX ret = TypeX.forName(name);
+ ret.typeParameters = new TypeX[paramTypeNames.length];
+ for (int i = 0; i < paramTypeNames.length; i++) {
+ ret.typeParameters[i] = TypeX.forName(paramTypeNames[i]);
+ }
+ // sig for e.g. List<String> is Ljava/util/List<Ljava/lang/String;>;
+ StringBuffer sigAddition = new StringBuffer();
+ sigAddition.append("<");
+ for (int i = 0; i < ret.typeParameters.length; i++) {
+ sigAddition.append(ret.typeParameters[i].signature);
+ sigAddition.append(">");
+ sigAddition.append(";");
+ }
+ ret.signature = ret.signature + sigAddition.toString();
+ return ret;
+ }
+
/**
* Creates a new type array with a fresh type appended to the end.
*
@@ -205,6 +232,15 @@ public class TypeX implements AnnotatedElement {
public String getName() {
return signatureToName(signature);
}
+
+ public String getBaseName() {
+ String name = getName();
+ if (isParameterized()) {
+ return name.substring(0,name.indexOf("<"));
+ } else {
+ return name;
+ }
+ }
/**
* Returns an array of strings representing the java langauge names of
@@ -250,6 +286,14 @@ public class TypeX implements AnnotatedElement {
public final boolean isArray() {
return signature.startsWith("[");
}
+
+ /**
+ * Determines if this represents a parameterized type.
+ */
+ public final boolean isParameterized() {
+ return signature.indexOf("<") != -1;
+ //(typeParameters != null) && (typeParameters.length > 0);
+ }
/**
* Returns a TypeX object representing the effective outermost enclosing type
@@ -603,7 +647,48 @@ public class TypeX implements AnnotatedElement {
case 'I': return "int";
case 'J': return "long";
case 'L':
- return signature.substring(1, signature.length() - 1).replace('/', '.');
+ String name = signature.substring(1, signature.length() - 1).replace('/', '.');
+ if (name.indexOf("<") == -1) return name;
+ // signature for parameterized types is e.g.
+ // List<String> -> Ljava/util/List<Ljava/lang/String;>;
+ // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
+ StringBuffer nameBuff = new StringBuffer();
+ boolean justSeenLeftArrowChar = false;
+ boolean justSeenSemiColon= false;
+ int paramNestLevel = 0;
+ for (int i = 0 ; i < name.length(); i++) {
+ char c = name.charAt(i);
+ switch (c) {
+ case '<' :
+ justSeenLeftArrowChar = true;
+ paramNestLevel++;
+ nameBuff.append(c);
+ break;
+ case ';' :
+ justSeenSemiColon = true;
+ break;
+ case '>' :
+ paramNestLevel--;
+ nameBuff.append(c);
+ break;
+ case 'L' :
+ if (justSeenLeftArrowChar) {
+ justSeenLeftArrowChar = false;
+ break;
+ }
+ if (justSeenSemiColon) {
+ nameBuff.append(",");
+ } else {
+ nameBuff.append("L");
+ }
+ break;
+ default:
+ justSeenSemiColon = false;
+ justSeenLeftArrowChar = false;
+ nameBuff.append(c);
+ }
+ }
+ return nameBuff.toString();
case 'S': return "short";
case 'V': return "void";
case 'Z': return "boolean";
@@ -631,7 +716,27 @@ public class TypeX implements AnnotatedElement {
// 1) If it is already an array type, do not mess with it.
if (name.charAt(0)=='[' && name.charAt(name.length()-1)==';') return name;
- else return "L" + name.replace('.', '/') + ";";
+ else {
+ if (name.indexOf("<") == -1) {
+ // not parameterised
+ return "L" + name.replace('.', '/') + ";";
+ } else {
+ StringBuffer nameBuff = new StringBuffer();
+ nameBuff.append("L");
+ for (int i = 0; i < name.length(); i++) {
+ char c = name.charAt(i);
+ switch (c) {
+ case '.' : nameBuff.append('/'); break;
+ case '<' : nameBuff.append("<L"); break;
+ case '>' : nameBuff.append(";>"); break;
+ case ',' : nameBuff.append(";L"); break;
+ default: nameBuff.append(c);
+ }
+ }
+ nameBuff.append(";");
+ return nameBuff.toString();
+ }
+ }
}
else
throw new BCException("Bad type name: " + name);
@@ -721,6 +826,10 @@ public class TypeX implements AnnotatedElement {
}
}
+ public TypeX[] getTypeParameters() {
+ return typeParameters == null ? new TypeX[0] : typeParameters;
+ }
+
/**
* Doesn't include the package
*/
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
index ca7e0a211..04ec34815 100644
--- a/weaver/src/org/aspectj/weaver/World.java
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -137,6 +137,11 @@ public abstract class World implements Dump.INode {
dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
}
}
+ if (ty.isParameterized()) {
+ for (int i = 0; i < ty.typeParameters.length; i++) {
+ ty.typeParameters[i] = resolve(ty.typeParameters[i],allowMissing);
+ }
+ }
//System.out.println("ret: " + ret);
typeMap.put(signature, ret);
return ret;
@@ -147,7 +152,14 @@ public abstract class World implements Dump.INode {
return resolve(TypeX.forName(name));
}
protected final ResolvedTypeX resolveObjectType(TypeX ty) {
- ResolvedTypeX.Name name = new ResolvedTypeX.Name(ty.getSignature(), this);
+ String signature = ty.getSignature();
+ if (signature.indexOf("<") != -1) {
+ // extract the raw type...
+ // XXX - might need to do more in the future to propagate full parameterized info...
+ signature = signature.substring(0,signature.indexOf("<"));
+ }
+
+ ResolvedTypeX.Name name = new ResolvedTypeX.Name(signature, this);
ResolvedTypeX.ConcreteName concreteName = resolveObjectType(name);
if (concreteName == null) return ResolvedTypeX.MISSING;
name.setDelegate(concreteName);
diff --git a/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java b/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java
index 3219b2f15..1ba812845 100644
--- a/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java
+++ b/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java
@@ -61,6 +61,21 @@ public class TypeXTestCase extends TestCase {
assertEquals(t.getOutermostType(), TypeX.forName("java.util.Map"));
assertEquals(TypeX.forName("java.util.Map").getOutermostType(), TypeX.forName("java.util.Map"));
}
+
+ public void testNameAndSigWithParameters() {
+ TypeX t = TypeX.forName("java.util.List<java.lang.String>");
+ assertEquals(t.getName(),"java.util.List<java.lang.String>");
+ assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;");
+ t = new TypeX("Ljava/util/List<Ljava/lang/String;>;");
+ assertEquals(t.getName(),"java.util.List<java.lang.String>");
+ assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;");
+ t = TypeX.forName("java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+ assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+ assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+ t = new TypeX("Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+ assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+ assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+ }
private void isPrimitiveTest(TypeX[] types, boolean[] isPrimitives) {
for (int i = 0, len = types.length; i < len; i++) {