diff options
6 files changed, 86 insertions, 22 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index c3756aec0..cb5d706e1 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -26,6 +26,7 @@ import java.util.Set; import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration; import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration; import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.WeaveMessage; import org.aspectj.bridge.context.CompilationAndWeavingContext; import org.aspectj.bridge.context.ContextToken; @@ -57,6 +58,7 @@ import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.ReferenceType; import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.TypeVariable; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; @@ -213,6 +215,13 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC } } + for (int i = lastCompletedUnitIndex +1; i<=lastUnitIndex; i++) { + SourceTypeBinding[] b = units[i].scope.topLevelTypes; + for (int j = 0; j < b.length; j++) { + verifyAnyTypeParametersMeetBounds(b[j]); + } + } + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { SourceTypeBinding[] b = units[i].scope.topLevelTypes; for (int j = 0; j < b.length; j++) { @@ -243,6 +252,42 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC /** + * For any given sourcetypebinding, this method checks that if it is a parameterized aspect that + * the type parameters specified for any supertypes meet the bounds for the generic type + * variables. + */ + private void verifyAnyTypeParametersMeetBounds(SourceTypeBinding sourceType) { + ResolvedType onType = factory.fromEclipse(sourceType); + if (onType.isAspect()) { + ResolvedType superType = factory.fromEclipse(sourceType.superclass); + // Don't need to check if it was used in its RAW form or isnt generic + if (superType.isGenericType() || superType.isParameterizedType()) { + TypeVariable[] typeVariables = superType.getTypeVariables(); + UnresolvedType[] typeParams = superType.getTypeParameters(); + if (typeVariables!=null && typeParams!=null) { + for (int i = 0; i < typeVariables.length; i++) { + boolean ok = typeVariables[i].canBeBoundTo(typeParams[i].resolve(factory.getWorld())); + if (!ok) { // the supplied parameter violates the bounds + // Type {0} does not meet the specification for type parameter {1} ({2}) in generic type {3} + String msg = + WeaverMessages.format( + WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS, + typeParams[i], + new Integer(i+1), + typeVariables[i].getDisplayName(), + superType.getGenericType().getName()); + factory.getWorld().getMessageHandler().handleMessage(MessageUtil.error(msg,onType.getSourceLocation())); + } + } + } + } + } + + + + } + + /** * Find all the ITDs and Declares, but it is important we do this from the supertypes * down to the subtypes. * @param sourceType @@ -443,8 +488,12 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC Collection declareParents, Collection declareAnnotationOnTypes, boolean skipInners) { ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, sourceType.sourceName); - + + ResolvedType onType = factory.fromEclipse(sourceType); + + + // AMC we shouldn't need this when generic sigs are fixed?? if (onType.isRawType()) onType = onType.getGenericType(); @@ -550,24 +599,11 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC needOldStyleWarning = false; } onType.addInterTypeMunger(munger); - /* - //TODO: Andy Should be done at weave time. - // Unfortunately we can't do it at weave time unless the type mungers remember where - // they came from. Thats why we do it here during complation because at this time - // they do know their source location. I've put a flag in ResolvedTypeMunger that - // records whether type mungers are currently set to remember their source location. - // The flag is currently set to false, it should be set to true when we do the - // work to version all AspectJ attributes. - // (When done at weave time, it is done by invoking addRelationship() on - // AsmRelationshipProvider (see BCELTypeMunger) - if (!ResolvedTypeMunger.persistSourceLocation) // Do it up front if we bloody have to - AsmInterTypeRelationshipProvider.getDefault().addRelationship(onType, munger); - */ } } - //???onType.checkInterTypeMungers(); + onType.checkInterTypeMungers(); for (Iterator i = onType.getInterTypeMungers().iterator(); i.hasNext();) { EclipseTypeMunger munger = (EclipseTypeMunger) i.next(); diff --git a/tests/java5/generics/genericaspects/GenericAspectK.aj b/tests/java5/generics/genericaspects/GenericAspectK.aj index 5c4b72f93..2a15c0aee 100644 --- a/tests/java5/generics/genericaspects/GenericAspectK.aj +++ b/tests/java5/generics/genericaspects/GenericAspectK.aj @@ -4,13 +4,13 @@ abstract aspect GenericAspect<A,B> { interface SimpleI<L extends Number> {} - declare parents: A implements SimpleI<B>; + declare parents: A implements SimpleI<B>; // Error: 'B' specified in the GenericAspect declaration doesnt say 'B extends Number' public N SimpleI<N>.m4(N n) { System.err.println(n);return n;} } -aspect GenericAspectI extends GenericAspect<Base,String> { // error, String doesnt meet bounds in SimpleI<> in the generic aspect +aspect GenericAspectK extends GenericAspect<Base,String> { // Error: String doesnt extend Number public static void main(String []argv) { Base b = new Base(); String s = b.m4("hello"); diff --git a/tests/java5/generics/genericaspects/GenericAspectK2.aj b/tests/java5/generics/genericaspects/GenericAspectK2.aj new file mode 100644 index 000000000..2c4ce99a1 --- /dev/null +++ b/tests/java5/generics/genericaspects/GenericAspectK2.aj @@ -0,0 +1,23 @@ +import java.util.*; + +abstract aspect GenericAspect<A,B extends Number> { + + interface SimpleI<L extends Number> {} + + declare parents: A implements SimpleI<B>; + + public N SimpleI<N>.m4(N n) { System.err.println(n);return n;} + +} + +aspect GenericAspectK2 extends GenericAspect<Base,String> { // Error: String doesnt meet bounds for B in GenericAspect + public static void main(String []argv) { + Base b = new Base(); + String s = b.m4("hello"); + if (!s.equals("hello")) + throw new RuntimeException("Not hello?? "+s); + } +} + +class Base {} + diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java index 6348d6371..a3462950a 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java @@ -347,14 +347,13 @@ public class GenericsTests extends XMLBasedAjcTestCase { public void testSophisticatedAspectsC() {runTest("uberaspects - C");} public void testSophisticatedAspectsD() {runTest("uberaspects - D");} public void testSophisticatedAspectsE() {runTest("uberaspects - E");} -// public void testSophisticatedAspectsF() {runTest("uberaspects - F");} field ITD collapses to Number from tvar.. + public void testSophisticatedAspectsF() {runTest("uberaspects - F");} public void testSophisticatedAspectsG() {runTest("uberaspects - G");} public void testSophisticatedAspectsH() {runTest("uberaspects - H");} public void testSophisticatedAspectsI() {runTest("uberaspects - I");} public void testSophisticatedAspectsJ() {runTest("uberaspects - J");} - // next test commented out, error message is less than ideal - see - // comment in test program as to what should be expected - //public void testSophisticatedAspectsK() {runTest("uberaspects - K");} + public void testSophisticatedAspectsK() {runTest("uberaspects - K");} + public void testSophisticatedAspectsK2(){runTest("uberaspects - K2");} public void testSophisticatedAspectsL() {runTest("uberaspects - L");} public void testSophisticatedAspectsM() {runTest("uberaspects - M");} public void testSophisticatedAspectsN() {runTest("uberaspects - N");} diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index b4648155f..d0aaa64ca 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -3616,9 +3616,15 @@ </ajc-test> <ajc-test dir="java5/generics/genericaspects/" title="uberaspects - K"> <compile files="GenericAspectK.aj" options="-1.5"> + <message kind="error" line="7" text="B does not meet the specification for type parameter 1 (L extends java.lang.Number) in generic type GenericAspect$SimpleI"/> <message kind="error" line="16" text="The method m4(String) is undefined for the type Base"/> </compile> </ajc-test> + <ajc-test dir="java5/generics/genericaspects/" title="uberaspects - K2"> + <compile files="GenericAspectK2.aj" options="-1.5"> + <message kind="error" line="13" text="Type java.lang.String does not meet the specification for type parameter 2 (B extends java.lang.Number) in generic type GenericAspect"/> + </compile> + </ajc-test> <ajc-test dir="java5/generics/genericaspects/" title="uberaspects - L"> <compile files="GenericAspectL.aj" options="-1.5"/> <run class="GenericAspectL"/> diff --git a/weaver/src/org/aspectj/weaver/ResolvedType.java b/weaver/src/org/aspectj/weaver/ResolvedType.java index 257cfb58c..e5bccfa47 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedType.java +++ b/weaver/src/org/aspectj/weaver/ResolvedType.java @@ -1151,7 +1151,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next(); if (munger.getSignature() != null && munger.getSignature().isAbstract()) { // Rule 1 if (munger.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) { - ;//ignore for @AJ ITD as munger.getSingature() is the interface method hence abstract + ;//ignore for @AJ ITD as munger.getSignature() is the interface method hence abstract } else { world.getMessageHandler().handleMessage( new Message("must implement abstract inter-type declaration: " + munger.getSignature(), |