--- /dev/null
+/* *******************************************************************
+ * 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;
+ }
+
+
+
+}
--- /dev/null
+/* *******************************************************************
+ * 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;
+ }
+
+}
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;
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
*/
<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>
--- /dev/null
+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
--- /dev/null
+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;
+ }
+}
// 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) &&
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,
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,
onGen);
InstructionList body = mg.getBody();
+ if (onGen.isInterface()) return mg;
+
// assert (!superMethod.isStatic())
InstructionFactory fact = onGen.getFactory();
int pos = 0;