Browse Source

tests and fix for Bugzilla Bug 39993

   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
tags/V1_1_1
jhugunin 21 years ago
parent
commit
026b2728ae

+ 84
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperFixerVisitor.java View File

@@ -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;
}


}

+ 36
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterSuperReference.java View File

@@ -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;
}

}

+ 13
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java View 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
*/

+ 13
- 0
tests/ajcTests.xml View File

@@ -6420,4 +6420,17 @@
<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>

+ 16
- 0
tests/bugs/MultipleSuperCf.java View File

@@ -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
}
}

+ 50
- 0
tests/bugs/OverridingInterfaceObjectMethod.java View File

@@ -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;
}
}

+ 31
- 16
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java View 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;

Loading…
Cancel
Save