return ret;
}
-
private static String getName(TypeBinding binding) {
+ if (binding instanceof TypeVariableBinding) {
+ // The first bound may be null - so default to object?
+ TypeVariableBinding tvb = (TypeVariableBinding)binding;
+ if (tvb.firstBound!=null) {
+ return getName(tvb.firstBound);
+ } else {
+ return getName(tvb.superclass);
+ }
+ }
+
if (binding instanceof ReferenceBinding) {
return new String(
CharOperation.concatWith(((ReferenceBinding)binding).compoundName, '.'));
+ /**
+ * Some generics notes:
+ *
+ * Andy 6-May-05
+ * We were having trouble with parameterized types in a couple of places - due to TypeVariableBindings. When we
+ * see a TypeVariableBinding now we default to either the firstBound if it is specified or java.lang.Object. Not
+ * sure when/if this gets us unstuck? It does mean we forget that it is a type variable when going back
+ * the other way from the TypeX and that would seem a bad thing - but I've yet to see the reason we need to
+ * remember the type variable.
+ */
//??? going back and forth between strings and bindings is a waste of cycles
public static TypeX fromBinding(TypeBinding binding) {
if (binding instanceof HelperInterfaceBinding) {
if (binding instanceof TypeVariableBinding) {
// this is a type variable...
TypeVariableBinding tvb = (TypeVariableBinding) binding;
- return TypeX.forName(getName(tvb.firstBound)); // XXX needs more investigation as to whether this is correct in all cases
+ // This code causes us to forget its a TVB which we will need when going back the other way...
+ if (tvb.firstBound!=null) {
+ return TypeX.forName(getName(tvb.firstBound)); // XXX needs more investigation as to whether this is correct in all cases
+ } else {
+ return TypeX.forName(getName(tvb.superclass));
+ }
}
// FIXME asc/amc cope properly with RawTypeBindings
if (binding instanceof ParameterizedTypeBinding && !(binding instanceof RawTypeBinding)) {
--- /dev/null
+import java.util.*;
+
+public aspect TestBug1 {
+ static <T> void addToEnv(Map<String,T> env, String key, T value) {
+ env.put(key, value);
+ }
+
+ public static void main(String[] argv) {
+ Map<String,Integer> msi = new HashMap<String,Integer>();
+ addToEnv(msi,"andy",new Integer(42));
+
+ if (msi.get("andy")!=42) throw new RuntimeException("Failed to add");
+ }
+}
+
--- /dev/null
+import java.util.*;
+
+public aspect TestBug2 {
+ static <T> T lookupEnv(Map<String,T> env, String key) {
+ return env.get(key);
+ }
+
+ public static void main(String[] argv) {
+ Map<String,Integer> msi = new HashMap<String,Integer>();
+ msi.put("andy",42);
+ if (lookupEnv(msi,"andy")!=42) throw new RuntimeException("Failed to lookup");
+ }
+}
public void testITDReturningParameterizedType() {
runTest("ITD with parameterized type");
}
+
+ public void testPR91267_1() {
+ runTest("NPE using generic methods in aspects 1");
+ }
+
+ public void testPR91267_2() {
+ runTest("NPE using generic methods in aspects 2");
+ }
}
<compile files="Test3.java" options="-1.5"/>
<run class="Test3"/>
</ajc-test>
+
+ <ajc-test dir="java5/generics/bugs/pr91267" title="NPE using generic methods in aspects 1" vm="1.5">
+ <compile files="TestBug1.aj" options="-1.5"/>
+ <run class="TestBug1"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/bugs/pr91267" title="NPE using generic methods in aspects 2" vm="1.5">
+ <compile files="TestBug2.aj" options="-1.5"/>
+ <run class="TestBug2"/>
+ </ajc-test>
</suite>
\ No newline at end of file
public static TypeX forName(String name) {
return forSignature(nameToSignature(name));
}
+
/** Constructs a TypeX for each java language type name in an incoming array.
*
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(";");
+ sigAddition.append(ret.typeParameters[i].signature);
}
+ sigAddition.append(">");
+ sigAddition.append(";");
ret.signature = ret.signature + sigAddition.toString();
return ret;
}