Bläddra i källkod

this set of commits teaches the TypeX world about parameterized types. it handles passing of parameterized types into the weaver from Eclipse, and back out again. Fixes the ITD and parameterized types issue that shows up in the examples. Much more work to be done in this area of course before M3.

tags/PRE_ANDY
acolyer 19 år sedan
förälder
incheckning
7a639d019a

+ 37
- 11
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java Visa fil

import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 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.LookupEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 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.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope; 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.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 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.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
/** /**
* @author Jim Hugunin * @author Jim Hugunin
TypeVariableBinding tvb = (TypeVariableBinding) binding; TypeVariableBinding tvb = (TypeVariableBinding) binding;
return TypeX.forName(getName(tvb.firstBound)); // XXX needs more investigation as to whether this is correct in all cases 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)); return TypeX.forName(getName(binding));
} }


typeX = typeX.getComponentType(); typeX = typeX.getComponentType();
} }
return lookupEnvironment.createArrayType(makeTypeBinding(typeX), dim); 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 { } 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) { public TypeBinding[] makeTypeBindings(TypeX[] types) {
int len = types.length; int len = types.length;

+ 2
- 0
tests/java5/generics/ITDReturningParameterizedType.aj Visa fil



public aspect ITDReturningParameterizedType { public aspect ITDReturningParameterizedType {
private List<String> myStrings = new ArrayList<String>();
private List<String> C.strings = new ArrayList<String>(); private List<String> C.strings = new ArrayList<String>();
public List<String> C.getStrings() { public List<String> C.getStrings() {

+ 1
- 1
tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java Visa fil

suite.addTest(SuppressedWarnings.suite()); suite.addTest(SuppressedWarnings.suite());
suite.addTest(DeclareAnnotationTests.suite()); suite.addTest(DeclareAnnotationTests.suite());
suite.addTest(GenericsTests.suite());
suite.addTest(AtAjSyntaxTests.suite()); suite.addTest(AtAjSyntaxTests.suite());
//$JUnit-END$ //$JUnit-END$
return suite; return suite;

+ 112
- 3
weaver/src/org/aspectj/weaver/TypeX.java Visa fil

* This is the bytecode string representation of this Type * This is the bytecode string representation of this Type
*/ */
protected String signature; 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 * @param signature the bytecode string representation of this Type
} }
return ret; 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. * Creates a new type array with a fresh type appended to the end.
* *
public String getName() { public String getName() {
return signatureToName(signature); 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 * Returns an array of strings representing the java langauge names of
public final boolean isArray() { public final boolean isArray() {
return signature.startsWith("["); 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 * Returns a TypeX object representing the effective outermost enclosing type
case 'I': return "int"; case 'I': return "int";
case 'J': return "long"; case 'J': return "long";
case 'L': 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 'S': return "short";
case 'V': return "void"; case 'V': return "void";
case 'Z': return "boolean"; case 'Z': return "boolean";
// 1) If it is already an array type, do not mess with it. // 1) If it is already an array type, do not mess with it.
if (name.charAt(0)=='[' && name.charAt(name.length()-1)==';') return name; 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 else
throw new BCException("Bad type name: " + name); throw new BCException("Bad type name: " + name);
} }
} }
public TypeX[] getTypeParameters() {
return typeParameters == null ? new TypeX[0] : typeParameters;
}
/** /**
* Doesn't include the package * Doesn't include the package
*/ */

+ 13
- 1
weaver/src/org/aspectj/weaver/World.java Visa fil

dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName())); 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); //System.out.println("ret: " + ret);
typeMap.put(signature, ret); typeMap.put(signature, ret);
return ret; return ret;
return resolve(TypeX.forName(name)); return resolve(TypeX.forName(name));
} }
protected final ResolvedTypeX resolveObjectType(TypeX ty) { 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); ResolvedTypeX.ConcreteName concreteName = resolveObjectType(name);
if (concreteName == null) return ResolvedTypeX.MISSING; if (concreteName == null) return ResolvedTypeX.MISSING;
name.setDelegate(concreteName); name.setDelegate(concreteName);

+ 15
- 0
weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java Visa fil

assertEquals(t.getOutermostType(), TypeX.forName("java.util.Map")); assertEquals(t.getOutermostType(), TypeX.forName("java.util.Map"));
assertEquals(TypeX.forName("java.util.Map").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) { private void isPrimitiveTest(TypeX[] types, boolean[] isPrimitives) {
for (int i = 0, len = types.length; i < len; i++) { for (int i = 0, len = types.length; i < len; i++) {

Laddar…
Avbryt
Spara