]> source.dussan.org Git - aspectj.git/commitdiff
280383: test and fix: itd ctor handles and npe with default ctor itd
authoraclement <aclement>
Tue, 16 Jun 2009 22:09:30 +0000 (22:09 +0000)
committeraclement <aclement>
Tue, 16 Jun 2009 22:09:30 +0000 (22:09 +0000)
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java

index 8bc56df311c87fd6f62da8450b384efe19b39a62..bcc22be25d172b2af276add78889dcb7d73e36f1 100644 (file)
  *     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 <code>preMethod</code> 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
+ * <code>preMethod</code> 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("<init>");
                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, "<init>", UnresolvedType.NONE));
+                       ((NewConstructorTypeMunger) munger).setExplicitConstructor(new ResolvedMemberImpl(Member.CONSTRUCTOR, world
+                                       .fromBinding(onTypeBinding.superclass()), 0, ResolvedType.VOID, "<init>", 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;
        }
-       
+
 }
index 789f4b9a915584088b102372e98a816ead8d8c43..20d74a724bec5600d8252d9f66a86b4a7cded599 100644 (file)
@@ -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);