From 8e079ecde2315294e16de8304899d19acdd15c36 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Fri, 16 Dec 2016 15:46:48 -0800 Subject: [PATCH] 509327: Minor fixes to improve the situation, wip --- .../aspectj/weaver/patterns/ArgsPointcut.java | 3 +- .../JavaLangTypeToResolvedTypeConverter.java | 12 +- .../weaver/reflect/ReflectionWorldTest.java | 162 +++++++++++++++++- 3 files changed, 173 insertions(+), 4 deletions(-) diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java index 4898a92b5..56b1a4dc5 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java @@ -57,7 +57,7 @@ public class ArgsPointcut extends NameBindingPointcut { return arguments; } - public Pointcut parameterizeWith(Map typeVariableMap, World w) { + public Pointcut parameterizeWith(Map typeVariableMap, World w) { ArgsPointcut ret = new ArgsPointcut(this.arguments.parameterizeWith(typeVariableMap, w)); ret.copyLocationFrom(this); return ret; @@ -114,7 +114,6 @@ public class ArgsPointcut extends NameBindingPointcut { argumentsToMatchAgainst = argsSubset; } } - return argumentsToMatchAgainst; } diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/JavaLangTypeToResolvedTypeConverter.java b/weaver5/java5-src/org/aspectj/weaver/reflect/JavaLangTypeToResolvedTypeConverter.java index 51a9a4e84..41ab968a7 100644 --- a/weaver5/java5-src/org/aspectj/weaver/reflect/JavaLangTypeToResolvedTypeConverter.java +++ b/weaver5/java5-src/org/aspectj/weaver/reflect/JavaLangTypeToResolvedTypeConverter.java @@ -66,10 +66,20 @@ public class JavaLangTypeToResolvedTypeConverter { return getWorld().resolve(name); } } else if (type instanceof ParameterizedType) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=509327 + // TODO should deal with the ownerType if it set, indicating this is possibly an inner type of a parameterized type +// Type ownerType = ((ParameterizedType) type).getOwnerType(); ParameterizedType parameterizedType = (ParameterizedType) type; ResolvedType baseType = fromType(parameterizedType.getRawType()); - if (!baseType.isRawType()) throw new IllegalStateException("Expected raw type form of "+parameterizedType.getRawType().getTypeName()); Type[] typeArguments = parameterizedType.getActualTypeArguments(); + if (baseType.isSimpleType() && typeArguments.length == 0) { + // 'type' is an inner type of some outer parameterized type + // For now just return the base type - in future create the parameterized form of the outer + // and use it with the inner. We return the base type to be compatible with what the + // code does that accesses the info from the bytecode (unlike this code which accesses it + // reflectively). + return baseType; + } ResolvedType[] resolvedTypeArguments = fromTypes(typeArguments); return TypeFactory.createParameterizedType(baseType, resolvedTypeArguments, getWorld()); } else if (type instanceof java.lang.reflect.TypeVariable) { diff --git a/weaver5/java5-testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java b/weaver5/java5-testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java index 5c08cf892..3dcbf45b2 100644 --- a/weaver5/java5-testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java +++ b/weaver5/java5-testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java @@ -11,11 +11,18 @@ * ******************************************************************/ package org.aspectj.weaver.reflect; -import junit.framework.TestCase; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.weaver.ReferenceType; +import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.World; +import org.aspectj.weaver.bcel.BcelWorld; + +import junit.framework.TestCase; public class ReflectionWorldTest extends TestCase { @@ -38,5 +45,158 @@ public class ReflectionWorldTest extends TestCase { assertEquals("int", UnresolvedType.INT, world.resolve(int.class)); assertEquals("void", UnresolvedType.VOID, world.resolve(void.class)); } + + public void testTypeConversions_509327() throws Exception { + ReflectionWorld rWorld = new ReflectionWorld(getClass().getClassLoader()); + JavaLangTypeToResolvedTypeConverter converter = new JavaLangTypeToResolvedTypeConverter(rWorld); + + // Check basic conversion of String to String + Method method = TestClass.class.getDeclaredMethod("m"); + Type stringType = method.getGenericReturnType(); + assertEquals("java.lang.String",stringType.getTypeName()); + ResolvedType stringResolvedType = converter.fromType(stringType); + assertEquals("java.lang.String",stringResolvedType.getName()); + + // public String m() { return ""; } + method = TestClass2.class.getDeclaredMethod("m"); + stringType = method.getGenericReturnType(); + assertEquals("java.lang.String",stringType.getTypeName()); + stringResolvedType = converter.fromType(stringType); + assertEquals("java.lang.String",stringResolvedType.getName()); + + // Verify that the conversion process creates the same thing as the bcel unpacking + + // Here the return type is a non-static inner of a generic class + // public Inner m2() { return null; } + method = TestClass2.class.getDeclaredMethod("m2"); + Type innerType = method.getGenericReturnType(); + assertEquals("org.aspectj.weaver.reflect.ReflectionWorldTest.org.aspectj.weaver.reflect.ReflectionWorldTest$TestClass2.Inner",innerType.getTypeName()); + ResolvedType rType_Inner = converter.fromType(innerType); + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2$Inner;",rType_Inner.getSignature()); + assertEquals(UnresolvedType.TypeKind.SIMPLE,rType_Inner.getTypekind()); + ResolvedType rType_Outer = rType_Inner.getOuterClass(); + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2;",rType_Outer.getSignature()); + + BcelWorld bWorld = new BcelWorld(getClass().getClassLoader(), IMessageHandler.THROW, null); + bWorld.setBehaveInJava5Way(true); + UnresolvedType javaUtilHashMap = UnresolvedType.forName("java.util.HashMap"); + ReferenceType rawType = (ReferenceType) bWorld.resolve(javaUtilHashMap); + assertNotNull(rawType); + + // Now use bcel to resolve the same m2 method, and compare the signatures of the return types + ResolvedType bResolved_TestClass2 = bWorld.resolve(UnresolvedType.forName(TestClass2.class.getName())); + assertNotNull(bResolved_TestClass2); + ResolvedMember bMethod_m2 = findMethod(bResolved_TestClass2,"m2"); + ResolvedType bType_Inner = (ResolvedType) bMethod_m2.getReturnType(); + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2$Inner;",bType_Inner.getSignature()); + assertEquals(UnresolvedType.TypeKind.SIMPLE,bType_Inner.getTypekind()); + ResolvedType bType_Outer = bType_Inner.getOuterClass(); + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2;",bType_Outer.getSignature()); + + assertEquals(bType_Inner.getSignature(),rType_Inner.getSignature()); + assertEquals(bType_Outer.getSignature(),rType_Outer.getSignature()); + } + + + public void testTypeConversions_509327_2() throws Exception { + ReflectionWorld world = new ReflectionWorld(getClass().getClassLoader()); + JavaLangTypeToResolvedTypeConverter converter = new JavaLangTypeToResolvedTypeConverter(world); + BcelWorld bWorld = new BcelWorld(getClass().getClassLoader(), IMessageHandler.THROW, null); + bWorld.setBehaveInJava5Way(true); + + // Slightly more advanced, now the method is returning a parameterized form of the outer + // generic class + + // public TestClass2.Inner m3() { return new TestClass2.Inner("Foo"); } + Method method = TestClass2.class.getDeclaredMethod("m3"); + Type type_ParameterizedInner = method.getGenericReturnType(); + assertEquals("org.aspectj.weaver.reflect.ReflectionWorldTest.org.aspectj.weaver.reflect.ReflectionWorldTest$TestClass2.Inner",type_ParameterizedInner.getTypeName()); + ResolvedType rType_ParameterizedInner = converter.fromType(type_ParameterizedInner); + // NOTE: DECLARED PARAMETERIZATION OF OUTER IS LOST + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2$Inner;",rType_ParameterizedInner.getSignature()); + + ResolvedType bResolved_TestClass2 = bWorld.resolve(UnresolvedType.forName(TestClass2.class.getName())); + assertNotNull(bResolved_TestClass2); + ResolvedMember bMethod_m3 = findMethod(bResolved_TestClass2,"m3"); + ResolvedType bType_Inner = (ResolvedType) bMethod_m3.getReturnType(); + // NOTE: DECLARED PARAMETERIZATION OF OUTER IS LOST + assertEquals("Lorg/aspectj/weaver/reflect/ReflectionWorldTest$TestClass2$Inner;",bType_Inner.getSignature()); + + assertEquals(UnresolvedType.TypeKind.SIMPLE,bType_Inner.getTypekind()); + ResolvedType bType_Outer = bType_Inner.getOuterClass(); + + // Fields seem to lose it too, although the backinggenericmember has the info +// ResolvedMember bField_f = findField(bResolved_TestClass2,"f"); +// ResolvedMember backingGenericMember = bField_f.getBackingGenericMember(); +// System.out.println(backingGenericMember); +// System.out.println(backingGenericMember.getGenericReturnType()); +// System.out.println(bField_f); +// System.out.println(bField_f.getSignature()); +// System.out.println(bField_f.getGenericReturnType()); + } + +// public void testbar() throws Exception { +// ReflectionWorld world = new ReflectionWorld(getClass().getClassLoader()); +// JavaLangTypeToResolvedTypeConverter converter = new JavaLangTypeToResolvedTypeConverter(world); +// +// // public TestClass2.Inner m3() { return new TestClass2.Inner("Foo"); } +// Method method = TestClass2.class.getDeclaredMethod("m3"); +// Type type_ParameterizedInner = method.getGenericReturnType(); +// assertEquals("org.aspectj.weaver.reflect.ReflectionWorldTest.org.aspectj.weaver.reflect.ReflectionWorldTest$TestClass2.Inner",type_ParameterizedInner.getTypeName()); +// ResolvedType rType_ParameterizedInner = converter.fromType(type_ParameterizedInner); +// System.out.println(rType_ParameterizedInner); +// System.out.println(type_ParameterizedInner.getTypeName()); +// } +// +// public void testfoo() { +// ReflectionWorld world = new ReflectionWorld(getClass().getClassLoader()); +// JavaLangTypeToResolvedTypeConverter converter = new JavaLangTypeToResolvedTypeConverter(world); +// BcelWorld bWorld = new BcelWorld(getClass().getClassLoader(), IMessageHandler.THROW, null); +// bWorld.setBehaveInJava5Way(true); +// +// +// ResolvedType bResolved_TestClass2 = bWorld.resolve(UnresolvedType.forName(TestClass2.class.getName())); +// ResolvedMember bField_f = findField(bResolved_TestClass2,"f"); +// System.out.println(bField_f); +// System.out.println(bField_f.getGenericReturnType()); +// System.out.println(bField_f.getReturnType()); +// System.out.println(bField_f.getBackingGenericMember().getGenericReturnType()); +// } + + static class TestClass { + public String m() { return ""; } + } + + static class TestClass2 { + class Inner { + T t; + Inner(T t) { + this.t = t; + } + } + public String m() { return ""; } + public Inner m2() { return null; } + public TestClass2 f; + public TestClass2.Inner m3() { return new TestClass2.Inner("Foo"); } + } + + private ResolvedMember findMethod(ResolvedType resolvedType, String methodName) { + for (ResolvedMember method: resolvedType.getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return method; + } + } + return null; + } + + private ResolvedMember findField(ResolvedType resolvedType, String fieldName) { + for (ResolvedMember field: resolvedType.getDeclaredFields()) { + if (field.getName().equals(fieldName)) { + return field; + } + } + return null; + } + } -- 2.39.5