]> source.dussan.org Git - aspectj.git/commitdiff
tests and fix for Bugzilla Bug 39993
authorjhugunin <jhugunin>
Tue, 22 Jul 2003 20:57:17 +0000 (20:57 +0000)
committerjhugunin <jhugunin>
Tue, 22 Jul 2003 20:57:17 +0000 (20:57 +0000)
   ajc stack trace on declaring hashcode() method in aspect

added extra error-test for using super inside an inter-type declaration on
an interface with multiple parents -- the correct parent is either
hard or impossible to determine in that case

org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperFixerVisitor.java [new file with mode: 0644]
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperReference.java [new file with mode: 0644]
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java
tests/ajcTests.xml
tests/bugs/MultipleSuperCf.java [new file with mode: 0644]
tests/bugs/OverridingInterfaceObjectMethod.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java

diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperFixerVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperFixerVisitor.java
new file mode 100644 (file)
index 0000000..bde3fd4
--- /dev/null
@@ -0,0 +1,84 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.SuperReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Walks the body of inter-type declarations and replaces SuperReference with InterSuperReference
+ * 
+ * @author Jim Hugunin
+ */
+
+public class InterSuperFixerVisitor extends AbstractSyntaxTreeVisitorAdapter {
+       InterTypeDeclaration dec;
+       ReferenceBinding onType;
+       TypeBinding superType;
+
+       EclipseFactory world; 
+       public InterSuperFixerVisitor(InterTypeDeclaration dec, EclipseFactory world, Scope scope) {
+               this.dec = dec;
+               this.onType = dec.onTypeBinding;
+               this.world = world;
+               
+               if (onType.superclass() != null) {
+                       superType = onType.superclass();
+               } else if (onType.superInterfaces() == null || onType.superInterfaces().length == 0) {
+                       superType = scope.getJavaLangObject();
+               } else if (onType.superInterfaces().length == 1) {
+                       superType = onType.superInterfaces()[0];
+               } else {
+                       superType = null;
+               }
+       }
+
+       public void endVisit(FieldReference ref, BlockScope scope) {
+               ref.receiver = fixReceiver(ref.receiver, scope);
+       }
+       public void endVisit(MessageSend send, BlockScope scope) {
+               send.receiver = fixReceiver(send.receiver, scope);
+       }
+
+       private Expression fixReceiver(Expression expression, BlockScope scope) {
+               if (expression instanceof SuperReference) {
+                       SuperReference superRef = (SuperReference) expression;
+                       if (superType == null) {
+                               ISourceLocation location =
+                                       new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(),
+                                                                               expression.sourceStart, expression.sourceEnd);
+                               
+                               world.showMessage(IMessage.ERROR, "multiple supertypes for this interface", location, null);
+                               dec.ignoreFurtherInvestigation = true;
+                       }
+                       //FIXME note error
+                       expression = new InterSuperReference(superRef, superType);      
+               }
+               return expression;
+       }
+       
+
+
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperReference.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperReference.java
new file mode 100644 (file)
index 0000000..f0ed406
--- /dev/null
@@ -0,0 +1,36 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ast.SuperReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Used to represent super references inside of inter-type declarations.  Special mechanism
+ * needed for handling in an interface context.
+ * 
+ * @author Jim Hugunin
+ */
+public class InterSuperReference extends SuperReference {
+       public InterSuperReference(SuperReference template, TypeBinding myType) {
+               super(template.sourceStart, template.sourceEnd);
+               this.resolvedType = myType;
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               return resolvedType;
+       }
+
+}
index 6c7d43b3d7e903227ec04d807be6702a1f33a871..7274367b340929e0d197867eb6cce221880b93d2 100644 (file)
@@ -17,6 +17,7 @@ import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
 import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
 import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
 import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
@@ -63,10 +64,22 @@ public abstract class InterTypeDeclaration extends MethodDeclaration {
                ClassScope newParent = new InterTypeScope(upperScope, onTypeBinding);
                scope.parent = newParent;
                this.scope.isStatic = Modifier.isStatic(declaredModifiers);
+               fixSuperCallsForInterfaceContext(upperScope);
+               if (ignoreFurtherInvestigation) return;
+               
                super.resolve(newParent);
                fixSuperCallsInBody();
        }
 
+       private void fixSuperCallsForInterfaceContext(ClassScope scope) {
+               if (onTypeBinding.isInterface()) {
+                       InterSuperFixerVisitor v =
+                               new InterSuperFixerVisitor(this, 
+                                               EclipseFactory.fromScopeLookupEnvironment(scope), scope);
+                       this.traverse(v, scope);
+               }
+       }
+
        /**
         * Called from AspectDeclarations.buildInterTypeAndPerClause
         */
index eed7526f93d27a32d937d3cbd19a011d430dec4a..3f01a7cb633237cc75c38114e8cb077bc3d49196 100644 (file)
         <compile files="SwitchInAround.java"/>
         <run class="SwitchInAround"/>
     </ajc-test>
+    
+    <ajc-test dir="bugs" pr="39993"
+        title="ajc stack trace on declaring hashcode() method in aspect">
+        <compile files="OverridingInterfaceObjectMethod.java"/>
+        <run class="OverridingInterfaceObjectMethod"/>
+    </ajc-test>
+
+    <ajc-test dir="bugs"
+        title="using super in method introduced on interface with multiple supertypes">
+        <compile files="MultipleSuperCf.java">
+               <message kind="error" line="14"/>
+        </compile>
+    </ajc-test>
 </suite>
diff --git a/tests/bugs/MultipleSuperCf.java b/tests/bugs/MultipleSuperCf.java
new file mode 100644 (file)
index 0000000..51404a3
--- /dev/null
@@ -0,0 +1,16 @@
+import org.aspectj.testing.Tester;
+
+interface B1 { }
+interface B2 { }
+
+interface D extends B1, B2 {}
+
+aspect A {
+       public int B1.m() {
+               return 2;
+       }
+       
+       public int D.m() {
+               return super.m();  // CE even though B1.m is the only thing that makes sense
+       }
+}
\ No newline at end of file
diff --git a/tests/bugs/OverridingInterfaceObjectMethod.java b/tests/bugs/OverridingInterfaceObjectMethod.java
new file mode 100644 (file)
index 0000000..d9ea38b
--- /dev/null
@@ -0,0 +1,50 @@
+import org.aspectj.testing.Tester;
+
+public class OverridingInterfaceObjectMethod {
+       private static final int VALUE = 10;
+       
+       public static void main(String[] args) {
+               Identifiable i = new C();
+               Tester.checkEqual(i.hashCode(), 42); //System.identityHashCode(i));
+               i.setId(new Id(VALUE));
+               Tester.checkEqual(i.hashCode(), VALUE);
+       }
+}
+
+//TODO explore complicated inheritance hierarchies
+
+class C implements Identifiable {}
+
+interface Base { }
+
+interface Identifiable extends Base {
+       void setId(Id id);
+       Id getId();
+}
+
+class Id {
+       public Id(int value) {
+               this.value = value;
+       }
+       int value;
+}
+aspect IdentifiableAspect {
+       private Id Identifiable.id = null;
+       public Id Identifiable.getId() {
+       return this.id;
+    }
+       public void Identifiable.setId(Id id) {
+               this.id = id;
+       }
+       public int Identifiable.hashCode() {
+               return (this.getId() == null)
+                       ? super.hashCode()
+                       : this.getId().value;
+       }
+       
+       public int Base.hashCode() {
+               return 42;
+       }
+}
index 9c1b28a0c53b5574f368a0ab0e5ac8492bbd3062..d75d94efe33793b71166acc7c17ea83260489a34 100644 (file)
@@ -339,21 +339,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        // XXX make sure to check that we set exceptions properly on this guy.
                        weaver.addLazyMethodGen(mg);
                        
-                       Set neededSuperCalls = munger.getSuperMethodsCalled();
-
-                       for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) {
-                               ResolvedMember superMethod = (ResolvedMember) iter.next();
-                               if (weaver.addDispatchTarget(superMethod)) {
-                                       //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
-                                       boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
-                                       String dispatchName;
-                                       if (isSuper) dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName());
-                                       else dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName());
-                                       LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper);
-
-                                       weaver.addLazyMethodGen(dispatcher);
-                               }
-                       }
+                       addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
                        
                return true;
                } else if (onInterface && gen.getType().isTopmostImplementor(onType) && 
@@ -388,12 +374,36 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        
                        weaver.addOrReplaceLazyMethodGen(mg);
                        
+                       addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
+                       
                        return true;
                } else {
                        return false;
                }
        }
 
+       private void addNeededSuperCallMethods(
+               BcelClassWeaver weaver,
+               ResolvedTypeX onType,
+               Set neededSuperCalls)
+       {
+               LazyClassGen gen = weaver.getLazyClassGen();
+               
+               for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) {
+                       ResolvedMember superMethod = (ResolvedMember) iter.next();
+                       if (weaver.addDispatchTarget(superMethod)) {
+                               //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
+                               boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
+                               String dispatchName;
+                               if (isSuper) dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName());
+                               else dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName());
+                               LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper);
+               
+                               weaver.addLazyMethodGen(dispatcher);
+                       }
+               }
+       }
+
 
        private boolean mungeNewConstructor(
                BcelClassWeaver weaver,
@@ -487,9 +497,12 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
                Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
                                
+               int modifiers = Modifier.PUBLIC;
+               if (onGen.isInterface()) modifiers |= Modifier.ABSTRACT;
+                               
                LazyMethodGen mg = 
                                new LazyMethodGen(
-                                       Modifier.PUBLIC,
+                                       modifiers,
                                        returnType,
                                        dispatchName,
                                        paramTypes,
@@ -497,6 +510,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                                        onGen);
                InstructionList body = mg.getBody();
                
+               if (onGen.isInterface()) return mg;
+               
                // assert (!superMethod.isStatic())
                InstructionFactory fact = onGen.getFactory();
                int pos = 0;