From e31f314dcdb74fe7372c008cba26f5ff60b269bd Mon Sep 17 00:00:00 2001 From: aclement Date: Tue, 16 Jun 2009 22:09:30 +0000 Subject: [PATCH] 280383: test and fix: itd ctor handles and npe with default ctor itd --- .../ast/InterTypeConstructorDeclaration.java | 305 +++++++++--------- .../core/builder/AsmElementFormatter.java | 2 +- 2 files changed, 155 insertions(+), 152 deletions(-) diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java index 8bc56df31..bcc22be25 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java @@ -10,73 +10,100 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.ajdt.internal.compiler.ast; import java.lang.reflect.Modifier; -import org.aspectj.ajdt.internal.compiler.lookup.*; + +import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation; +import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger; +import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope; import org.aspectj.bridge.ISourceLocation; -import org.aspectj.weaver.*; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.AjcMemberMaker; +import org.aspectj.weaver.Constants; +import org.aspectj.weaver.Member; +import org.aspectj.weaver.NameMangler; +import org.aspectj.weaver.NewConstructorTypeMunger; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedMemberImpl; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.UnresolvedType; /** * An inter-type constructor declaration. * - * This will generate two implementation methods in the aspect, the main one for the body - * of the constructor, and an additional preMethod for the code that - * runs before the super constructor is called. + * This will generate two implementation methods in the aspect, the main one for the body of the constructor, and an additional + * preMethod for the code that runs before the super constructor is called. * * @author Jim Hugunin */ -public class InterTypeConstructorDeclaration extends InterTypeDeclaration { +public class InterTypeConstructorDeclaration extends InterTypeDeclaration { private static final String SUPPRESSAJWARNINGS = "Lorg/aspectj/lang/annotation/SuppressAjWarnings;"; private static final String NOEXPLICITCONSTRUCTORCALL = "noExplicitConstructorCall"; private MethodDeclaration preMethod; private ExplicitConstructorCall explicitConstructorCall = null; - + public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) { super(result, onType); } - + public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { if (ignoreFurtherInvestigation) return; - parser.parse(this, unit); + parser.parse(this, unit); } - + protected char[] getPrefix() { return (NameMangler.ITD_PREFIX + "interConstructor$").toCharArray(); } public void resolve(ClassScope upperScope) { - if (munger == null || binding == null) ignoreFurtherInvestigation = true; - if (ignoreFurtherInvestigation) return; + if (munger == null || binding == null) + ignoreFurtherInvestigation = true; + if (ignoreFurtherInvestigation) + return; explicitConstructorCall = null; - if (statements != null && statements.length > 0 && - statements[0] instanceof ExplicitConstructorCall) - { + if (statements != null && statements.length > 0 && statements[0] instanceof ExplicitConstructorCall) { explicitConstructorCall = (ExplicitConstructorCall) statements[0]; statements = AstUtil.remove(0, statements); } - + preMethod = makePreMethod(upperScope, explicitConstructorCall); - - binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters); - this.arguments = AstUtil.insert( - AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), - this.arguments); - + + binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters); + this.arguments = AstUtil.insert(AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), this.arguments); + super.resolve(upperScope); - + // after annotations have been resolved... if (explicitConstructorCall == null) { raiseNoFieldInitializersWarning(); @@ -84,36 +111,39 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration { } /** - * Warning added in response to PR 62606 - if an ITD constructor does not make an explicit constructor - * call then field initializers in the target class will not be executed leading to unexpected behaviour. + * Warning added in response to PR 62606 - if an ITD constructor does not make an explicit constructor call then field + * initializers in the target class will not be executed leading to unexpected behaviour. */ private void raiseNoFieldInitializersWarning() { - if (suppressingNoExplicitConstructorCall()) return; + if (suppressingNoExplicitConstructorCall()) + return; EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope); - ISourceLocation location = - new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), - sourceStart(),sourceEnd()); + ISourceLocation location = new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), + sourceStart(), sourceEnd()); world.getWorld().getLint().noExplicitConstructorCall.signal(null, location); } - + /** * true iff constructor has @SuppressAjWarnings or @SuppressAjWarnings("xyz,noExplicitConstructorCall,def,...") + * * @return */ private boolean suppressingNoExplicitConstructorCall() { - if (this.annotations == null) return false; + if (this.annotations == null) + return false; for (int i = 0; i < this.annotations.length; i++) { if (new String(this.annotations[i].resolvedType.signature()).equals(SUPPRESSAJWARNINGS)) { if (this.annotations[i] instanceof MarkerAnnotation) { return true; - } else if (this.annotations[i] instanceof SingleMemberAnnotation){ + } else if (this.annotations[i] instanceof SingleMemberAnnotation) { SingleMemberAnnotation sma = (SingleMemberAnnotation) this.annotations[i]; if (sma.memberValue instanceof ArrayInitializer) { ArrayInitializer memberValue = (ArrayInitializer) sma.memberValue; for (int j = 0; j < memberValue.expressions.length; j++) { if (memberValue.expressions[j] instanceof StringLiteral) { StringLiteral val = (StringLiteral) memberValue.expressions[j]; - if (new String(val.source()).equals(NOEXPLICITCONSTRUCTORCALL)) return true; + if (new String(val.source()).equals(NOEXPLICITCONSTRUCTORCALL)) + return true; } } } @@ -122,193 +152,168 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration { } return false; } - - private MethodDeclaration makePreMethod(ClassScope scope, - ExplicitConstructorCall explicitConstructorCall) - { + + private MethodDeclaration makePreMethod(ClassScope scope, ExplicitConstructorCall explicitConstructorCall) { EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope); - + UnresolvedType aspectTypeX = world.fromBinding(binding.declaringClass); UnresolvedType targetTypeX = world.fromBinding(onTypeBinding); - + ArrayBinding objectArrayBinding = scope.createArrayType(scope.getJavaLangObject(), 1); - - + MethodDeclaration pre = new MethodDeclaration(compilationResult); pre.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic; pre.returnType = AstUtil.makeTypeReference(objectArrayBinding); pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray(); - - + pre.arguments = AstUtil.copyArguments(this.arguments); - - //XXX should do exceptions - + + // XXX should do exceptions + pre.scope = new MethodScope(scope, pre, true); - //??? do we need to do anything with scope??? - - + // ??? do we need to do anything with scope??? - // Use the factory to build a semi-correct resolvedmember - then patch it up with - // reset calls. This is SAFE + // Use the factory to build a semi-correct resolvedmember - then patch it up with + // reset calls. This is SAFE ResolvedMember preIntroducedConstructorRM = world.makeResolvedMember(binding); preIntroducedConstructorRM.resetName(NameMangler.preIntroducedConstructor(aspectTypeX, targetTypeX)); preIntroducedConstructorRM.resetModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL); preIntroducedConstructorRM.resetReturnTypeToObjectArray(); - + pre.binding = world.makeMethodBinding(preIntroducedConstructorRM); - + pre.bindArguments(); pre.bindThrownExceptions(); - - + if (explicitConstructorCall == null) { pre.statements = new Statement[] {}; } else { - pre.statements = new Statement[] { - explicitConstructorCall - }; + pre.statements = new Statement[] { explicitConstructorCall }; } - - InterTypeScope newParent = - new InterTypeScope(scope, onTypeBinding); + + InterTypeScope newParent = new InterTypeScope(scope, onTypeBinding); pre.scope.parent = newParent; - pre.resolveStatements(); //newParent); - - - + pre.resolveStatements(); // newParent); + int nParams = pre.arguments.length; MethodBinding explicitConstructor = null; if (explicitConstructorCall != null) { explicitConstructor = explicitConstructorCall.binding; // If it is null then we are going to report something else is wrong with this code! - if (explicitConstructor!=null && explicitConstructor.alwaysNeedsAccessMethod()) { + if (explicitConstructor != null && explicitConstructor.alwaysNeedsAccessMethod()) { explicitConstructor = explicitConstructor.getAccessMethod(true); } } - + int nExprs; - if (explicitConstructor == null) nExprs = 0; - else nExprs = explicitConstructor.parameters.length; - - + if (explicitConstructor == null) + nExprs = 0; + else + nExprs = explicitConstructor.parameters.length; + ArrayInitializer init = new ArrayInitializer(); init.expressions = new Expression[nExprs + nParams]; int index = 0; - for (int i=0; i < nExprs; i++) { - if (i >= explicitConstructorCall.arguments.length) { + for (int i = 0; i < nExprs; i++) { + if (i >= (explicitConstructorCall.arguments == null ? 0 : explicitConstructorCall.arguments.length)) { init.expressions[index++] = new NullLiteral(0, 0); continue; } - - + Expression arg = explicitConstructorCall.arguments[i]; - ResolvedMember conversionMethod = - AjcMemberMaker.toObjectConversionMethod(world.fromBinding(explicitConstructorCall.binding.parameters[i])); + ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world + .fromBinding(explicitConstructorCall.binding.parameters[i])); if (conversionMethod != null) { - arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), - new CastExpression(new NullLiteral(0, 0), - AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), - new Expression[] {arg }); + arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0, + 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), + new Expression[] { arg }); } init.expressions[index++] = arg; } - - for (int i=0; i < nParams; i++) { + + for (int i = 0; i < nParams; i++) { LocalVariableBinding binding = pre.arguments[i].binding; Expression arg = AstUtil.makeResolvedLocalVariableReference(binding); - ResolvedMember conversionMethod = - AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type)); + ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type)); if (conversionMethod != null) { - arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), - new CastExpression(new NullLiteral(0, 0), - AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), - new Expression[] {arg }); + arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0, + 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))), + new Expression[] { arg }); } init.expressions[index++] = arg; } - - init.binding =objectArrayBinding; - + + init.binding = objectArrayBinding; + ArrayAllocationExpression newArray = new ArrayAllocationExpression(); newArray.initializer = init; newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject()); newArray.dimensions = new Expression[1]; newArray.constant = Constant.NotAConstant; - - - - pre.statements = new Statement[] { - new ReturnStatement(newArray, 0, 0), - }; + pre.statements = new Statement[] { new ReturnStatement(newArray, 0, 0), }; return pre; } - - - - - public EclipseTypeMunger build(ClassScope classScope) { EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope); - + resolveOnType(classScope); - if (ignoreFurtherInvestigation) return null; - + if (ignoreFurtherInvestigation) + return null; + binding = classScope.referenceContext.binding.resolveTypesFor(binding); - - if (isTargetAnnotation(classScope,"constructor")) return null; // Error message output in isTargetAnnotation - if (isTargetEnum(classScope,"constructor")) return null; // Error message output in isTargetEnum - + + if (isTargetAnnotation(classScope, "constructor")) + return null; // Error message output in isTargetAnnotation + if (isTargetEnum(classScope, "constructor")) + return null; // Error message output in isTargetEnum + if (onTypeBinding.isInterface()) { - classScope.problemReporter().signalError(sourceStart, sourceEnd, - "can't define constructors on interfaces"); + classScope.problemReporter().signalError(sourceStart, sourceEnd, "can't define constructors on interfaces"); ignoreFurtherInvestigation = true; return null; } - + if (onTypeBinding.isNestedType()) { classScope.problemReporter().signalError(sourceStart, sourceEnd, - "can't define constructors on nested types (compiler limitation)"); + "can't define constructors on nested types (compiler limitation)"); ignoreFurtherInvestigation = true; return null; - } - + } + ResolvedType declaringTypeX = world.fromEclipse(onTypeBinding); ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding); - - if (interTypeScope==null) return null; // We encountered a problem building the scope, don't continue - error already reported - + if (interTypeScope == null) + return null; // We encountered a problem building the scope, don't continue - error already reported + // This signature represents what we want consumers of the targetted type to 'see' - ResolvedMember signature = world.makeResolvedMemberForITD(binding,onTypeBinding,interTypeScope.getRecoveryAliases()); + ResolvedMember signature = world.makeResolvedMemberForITD(binding, onTypeBinding, interTypeScope.getRecoveryAliases()); signature.resetKind(Member.CONSTRUCTOR); signature.resetName(""); int resetModifiers = declaredModifiers; - if (binding.isVarargs()) resetModifiers = resetModifiers | Constants.ACC_VARARGS; + if (binding.isVarargs()) + resetModifiers = resetModifiers | Constants.ACC_VARARGS; signature.resetModifiers(resetModifiers); - - ResolvedMember syntheticInterMember = - AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType); - - NewConstructorTypeMunger myMunger = - new NewConstructorTypeMunger(signature, syntheticInterMember, null, null,typeVariableAliases); + + ResolvedMember syntheticInterMember = AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType); + + NewConstructorTypeMunger myMunger = new NewConstructorTypeMunger(signature, syntheticInterMember, null, null, + typeVariableAliases); setMunger(myMunger); myMunger.check(world.getWorld()); - - this.selector = binding.selector = - NameMangler.postIntroducedConstructor( - world.fromBinding(binding.declaringClass), + + this.selector = binding.selector = NameMangler.postIntroducedConstructor(world.fromBinding(binding.declaringClass), declaringTypeX).toCharArray(); - + return new EclipseTypeMunger(world, myMunger, aspectType, this); } - - + private AjAttribute makeAttribute(EclipseFactory world) { - if (explicitConstructorCall != null && (explicitConstructorCall.binding!=null) && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) { + if (explicitConstructorCall != null && (explicitConstructorCall.binding != null) + && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) { MethodBinding explicitConstructor = explicitConstructorCall.binding; if (explicitConstructor.alwaysNeedsAccessMethod()) { explicitConstructor = explicitConstructor.getAccessMethod(true); @@ -316,28 +321,26 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration { if (explicitConstructor instanceof ParameterizedMethodBinding) { explicitConstructor = explicitConstructor.original(); } - ((NewConstructorTypeMunger)munger).setExplicitConstructor( - world.makeResolvedMember(explicitConstructor)); + ((NewConstructorTypeMunger) munger).setExplicitConstructor(world.makeResolvedMember(explicitConstructor)); } else { - ((NewConstructorTypeMunger)munger).setExplicitConstructor( - new ResolvedMemberImpl(Member.CONSTRUCTOR, - world.fromBinding(onTypeBinding.superclass()), - 0, ResolvedType.VOID, "", UnresolvedType.NONE)); + ((NewConstructorTypeMunger) munger).setExplicitConstructor(new ResolvedMemberImpl(Member.CONSTRUCTOR, world + .fromBinding(onTypeBinding.superclass()), 0, ResolvedType.VOID, "", UnresolvedType.NONE)); } return new AjAttribute.TypeMunger(munger); } - - + public void generateCode(ClassScope classScope, ClassFile classFile) { - if (ignoreFurtherInvestigation) return; + if (ignoreFurtherInvestigation) + return; EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope); classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world))); super.generateCode(classScope, classFile); -// classFile.codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS; + // classFile.codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS; preMethod.generateCode(classScope, classFile); } + protected Shadow.Kind getShadowKindForBody() { return Shadow.ConstructorExecution; } - + } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java index 789f4b9a9..20d74a724 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java @@ -189,7 +189,7 @@ public class AsmElementFormatter { // } // argumentsSignature.append(")"); // InterTypeConstructorDeclaration itcd = (InterTypeConstructorDeclaration)methodDeclaration; - node.setName(itd.getOnType().toString() + "." + itd.getOnType().toString()/* +argumentsSignature.toString() */); + node.setName(itd.getOnType().toString() + "." + itd.getOnType().toString().replace('.', '_')); } else { node.setKind(IProgramElement.Kind.ERROR); node.setName(name); -- 2.39.5