]> source.dussan.org Git - aspectj.git/commitdiff
194314: now copies the parameter names from the ITD to the dispatcher
authoraclement <aclement>
Thu, 29 Jan 2009 05:59:33 +0000 (05:59 +0000)
committeraclement <aclement>
Thu, 29 Jan 2009 05:59:33 +0000 (05:59 +0000)
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java

index cedc82c4d81971368ca2d1605d7560cb504a8a94..d0dffa6829a25da6b70c75140e98d1a48cbe9c93 100644 (file)
@@ -10,7 +10,6 @@
  *     PARC     initial implementation 
  * ******************************************************************/
 
-
 package org.aspectj.ajdt.internal.compiler.ast;
 
 import java.lang.reflect.Modifier;
@@ -20,6 +19,7 @@ import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
 import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter;
 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.Argument;
 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -28,6 +28,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.aspectj.org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+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.ReferenceBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
@@ -47,7 +48,7 @@ import org.aspectj.weaver.UnresolvedType;
 
 /**
  * An inter-type method declaration.
- *
+ * 
  * @author Jim Hugunin
  */
 public class InterTypeMethodDeclaration extends InterTypeDeclaration {
@@ -62,203 +63,214 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
                        parser.parse(this, unit);
                }
        }
-       
+
        protected char[] getPrefix() {
                return (NameMangler.ITD_PREFIX + "interMethod$").toCharArray();
        }
-       
+
        public boolean isFinal() {
-               return  (declaredModifiers & ClassFileConstants.AccFinal) != 0;         
+               return (declaredModifiers & ClassFileConstants.AccFinal) != 0;
        }
 
-       public void analyseCode(
-               ClassScope currentScope,
-               InitializationFlowContext flowContext,
-               FlowInfo flowInfo)
-       {
-               if (Modifier.isAbstract(declaredModifiers)) return;
-               
+       public void analyseCode(ClassScope currentScope, InitializationFlowContext flowContext, FlowInfo flowInfo) {
+               if (Modifier.isAbstract(declaredModifiers))
+                       return;
+
                super.analyseCode(currentScope, flowContext, flowInfo);
        }
-       
+
        public void resolve(ClassScope upperScope) {
-               if (munger == null) ignoreFurtherInvestigation = true;
+               if (munger == null)
+                       ignoreFurtherInvestigation = true;
                if (binding == null)
-            ignoreFurtherInvestigation = true;
-               if (ignoreFurtherInvestigation) return;
-               
+                       ignoreFurtherInvestigation = true;
+               if (ignoreFurtherInvestigation)
+                       return;
+
                if (!Modifier.isStatic(declaredModifiers)) {
-                       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);
+                       binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
                }
-                       
+
                super.resolve(upperScope);
        }
-       
-       
+
        public void resolveStatements() {
                checkAndSetModifiersForMethod();
-        if ((modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
-            if ((declaredModifiers & ClassFileConstants.AccAbstract) == 0)
-                scope.problemReporter().methodNeedBody(this);
-        } else {
-            // the method HAS a body --> abstract native modifiers are forbiden
-            if (((declaredModifiers & ClassFileConstants.AccAbstract) != 0))
-                scope.problemReporter().methodNeedingNoBody(this);
-        }        
-
-        // XXX AMC we need to do this, but I'm not 100% comfortable as I don't
-        // know why the return type is wrong in this case. Also, we don't seem to need
-        // to do it for args...
-        if (munger.getSignature().getReturnType().isRawType()) {
-               if (!binding.returnType.isRawType()) {
+               if ((modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
+                       if ((declaredModifiers & ClassFileConstants.AccAbstract) == 0)
+                               scope.problemReporter().methodNeedBody(this);
+               } else {
+                       // the method HAS a body --> abstract native modifiers are forbiden
+                       if (((declaredModifiers & ClassFileConstants.AccAbstract) != 0))
+                               scope.problemReporter().methodNeedingNoBody(this);
+               }
+
+               // XXX AMC we need to do this, but I'm not 100% comfortable as I don't
+               // know why the return type is wrong in this case. Also, we don't seem to need
+               // to do it for args...
+               if (munger.getSignature().getReturnType().isRawType()) {
+                       if (!binding.returnType.isRawType()) {
                                EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
-                       binding.returnType = world.makeTypeBinding(munger.getSignature().getReturnType()); 
-               }
-        }
-        
-        // check @Override annotation - based on MethodDeclaration.resolveStatements() @Override processing
+                               binding.returnType = world.makeTypeBinding(munger.getSignature().getReturnType());
+                       }
+               }
+
+               // check @Override annotation - based on MethodDeclaration.resolveStatements() @Override processing
                checkOverride: {
-                       if (this.binding == null) break checkOverride;
-                       if (this.scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) break checkOverride;
+                       if (this.binding == null)
+                               break checkOverride;
+                       if (this.scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5)
+                               break checkOverride;
                        boolean hasOverrideAnnotation = (this.binding.tagBits & TagBits.AnnotationOverride) != 0;
-                       
+
                        // Need to verify
                        if (hasOverrideAnnotation) {
-                               
+
                                // Work out the real method binding that we can use for comparison
                                EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
-                               MethodBinding realthing = world.makeMethodBinding(munger.getSignature(),munger.getTypeVariableAliases());
-                               
-                               boolean reportError = true;                             
+                               MethodBinding realthing = world.makeMethodBinding(munger.getSignature(), munger.getTypeVariableAliases());
+
+                               boolean reportError = true;
                                // Go up the hierarchy, looking for something we override
                                ReferenceBinding supertype = onTypeBinding.superclass();
-                               while (supertype!=null && reportError) {
+                               while (supertype != null && reportError) {
                                        MethodBinding[] possibles = supertype.getMethods(declaredSelector);
                                        for (int i = 0; i < possibles.length; i++) {
                                                MethodBinding mb = possibles[i];
 
                                                boolean couldBeMatch = true;
-                                               if (mb.parameters.length!=realthing.parameters.length) couldBeMatch=false;
+                                               if (mb.parameters.length != realthing.parameters.length)
+                                                       couldBeMatch = false;
                                                else {
                                                        for (int j = 0; j < mb.parameters.length && couldBeMatch; j++) {
-                                                               if (!mb.parameters[j].equals(realthing.parameters[j])) couldBeMatch=false;
+                                                               if (!mb.parameters[j].equals(realthing.parameters[j]))
+                                                                       couldBeMatch = false;
                                                        }
                                                }
                                                // return types compatible? (allow for covariance)
-                                               if (couldBeMatch && !returnType.resolvedType.isCompatibleWith(mb.returnType)) couldBeMatch=false;
-                                               if (couldBeMatch) reportError = false;
+                                               if (couldBeMatch && !returnType.resolvedType.isCompatibleWith(mb.returnType))
+                                                       couldBeMatch = false;
+                                               if (couldBeMatch)
+                                                       reportError = false;
                                        }
                                        supertype = supertype.superclass(); // superclass of object is null
                                }
                                // If we couldn't find something we override, report the error
-                               if (reportError) ((AjProblemReporter)this.scope.problemReporter()).itdMethodMustOverride(this,realthing);                       
+                               if (reportError)
+                                       ((AjProblemReporter) this.scope.problemReporter()).itdMethodMustOverride(this, realthing);
                        }
                }
-        
-               if (!Modifier.isAbstract(declaredModifiers)) super.resolveStatements();
+
+               if (!Modifier.isAbstract(declaredModifiers))
+                       super.resolveStatements();
                if (Modifier.isStatic(declaredModifiers)) {
                        // Check the target for ITD is not an interface
                        if (onTypeBinding.isInterface()) {
-                               scope.problemReporter().signalError(sourceStart, sourceEnd,
-                                       "methods in interfaces cannot be declared static");
+                               scope.problemReporter().signalError(sourceStart, sourceEnd, "methods in interfaces cannot be declared static");
                        }
                }
        }
-       
-       
 
        public EclipseTypeMunger build(ClassScope classScope) {
                EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(classScope);
-               
+
                resolveOnType(classScope);
-               if (ignoreFurtherInvestigation) return null;
+               if (ignoreFurtherInvestigation)
+                       return null;
 
                binding = classScope.referenceContext.binding.resolveTypesFor(binding);
                if (binding == null) {
                        // if binding is null, we failed to find a type used in the method params, this error
                        // has already been reported.
                        this.ignoreFurtherInvestigation = true;
-                       //return null;
-                       throw new AbortCompilationUnit(compilationResult,null);
+                       // return null;
+                       throw new AbortCompilationUnit(compilationResult, null);
                }
 
-               if (isTargetAnnotation(classScope,"method")) return null; // Error message output in isTargetAnnotation
-               if (isTargetEnum(classScope,"method")) return null; // Error message output in isTargetEnum
-               
-               if (interTypeScope==null) return null; // We encountered a problem building the scope, don't continue - error already reported
-               
+               if (isTargetAnnotation(classScope, "method"))
+                       return null; // Error message output in isTargetAnnotation
+               if (isTargetEnum(classScope, "method"))
+                       return null; // Error message output in isTargetEnum
+
+               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'
                // must use the factory method to build it since there may be typevariables from the binding
                // referred to in the parameters/returntype
-               ResolvedMember sig = factory.makeResolvedMemberForITD(binding,onTypeBinding,interTypeScope.getRecoveryAliases());
+               ResolvedMember sig = factory.makeResolvedMemberForITD(binding, onTypeBinding, interTypeScope.getRecoveryAliases());
                sig.resetName(new String(declaredSelector));
                int resetModifiers = declaredModifiers;
-               if (binding.isVarargs())  resetModifiers = resetModifiers | Constants.ACC_VARARGS;
-               sig.resetModifiers(resetModifiers); 
+               if (binding.isVarargs())
+                       resetModifiers = resetModifiers | Constants.ACC_VARARGS;
+               sig.resetModifiers(resetModifiers);
                NewMethodTypeMunger myMunger = new NewMethodTypeMunger(sig, null, typeVariableAliases);
                setMunger(myMunger);
                ResolvedType aspectType = factory.fromEclipse(classScope.referenceContext.binding);
-               ResolvedMember me =
-                       myMunger.getInterMethodBody(aspectType);
+               ResolvedMember me = myMunger.getInterMethodBody(aspectType);
                this.selector = binding.selector = me.getName().toCharArray();
                return new EclipseTypeMunger(factory, myMunger, aspectType, this);
        }
-       
-       
+
        private AjAttribute makeAttribute() {
                return new AjAttribute.TypeMunger(munger);
        }
-       
-       
+
        public void generateCode(ClassScope classScope, ClassFile classFile) {
                if (ignoreFurtherInvestigation) {
-                       //System.err.println("no code for " + this);
+                       // System.err.println("no code for " + this);
                        return;
                }
-               
+
                classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
-               
+
                if (!Modifier.isAbstract(declaredModifiers)) {
                        super.generateCode(classScope, classFile); // this makes the interMethodBody
                }
-               
-               // annotations on the ITD declaration get put on this method 
+
+               // annotations on the ITD declaration get put on this method
                generateDispatchMethod(classScope, classFile);
        }
-       
+
        public void generateDispatchMethod(ClassScope classScope, ClassFile classFile) {
                EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
-               
+
                UnresolvedType aspectType = world.fromBinding(classScope.referenceContext.binding);
                ResolvedMember signature = munger.getSignature();
-               
-               ResolvedMember dispatchMember = 
-                       AjcMemberMaker.interMethodDispatcher(signature, aspectType);
-               MethodBinding dispatchBinding = world.makeMethodBinding(dispatchMember,munger.getTypeVariableAliases(),munger.getSignature().getDeclaringType());
-               MethodBinding introducedMethod = 
-                       world.makeMethodBinding(AjcMemberMaker.interMethod(signature, aspectType, onTypeBinding.isInterface()),munger.getTypeVariableAliases());
-               
+
+               ResolvedMember dispatchMember = AjcMemberMaker.interMethodDispatcher(signature, aspectType);
+               MethodBinding dispatchBinding = world.makeMethodBinding(dispatchMember, munger.getTypeVariableAliases(), munger
+                               .getSignature().getDeclaringType());
+               MethodBinding introducedMethod = world.makeMethodBinding(AjcMemberMaker.interMethod(signature, aspectType, onTypeBinding
+                               .isInterface()), munger.getTypeVariableAliases());
+
                classFile.generateMethodInfoHeader(dispatchBinding);
                int methodAttributeOffset = classFile.contentsOffset;
-               
-               
-               // Watch out!  We are passing in 'binding' here (instead of dispatchBinding) so that
+
+               // Watch out! We are passing in 'binding' here (instead of dispatchBinding) so that
                // the dispatch binding attributes will include the annotations from the 'binding'.
                // There is a chance that something else on the binding (e.g. throws clause) might
                // damage the attributes generated for the dispatch binding.
-               int attributeNumber = classFile.generateMethodInfoAttribute(binding,
-                               false,
-                               makeEffectiveSignatureAttribute(signature, Shadow.MethodCall, false));
+               int attributeNumber = classFile.generateMethodInfoAttribute(binding, false, makeEffectiveSignatureAttribute(signature,
+                               Shadow.MethodCall, false));
                int codeAttributeOffset = classFile.contentsOffset;
                classFile.generateCodeAttributeHeader();
                CodeStream codeStream = classFile.codeStream;
                codeStream.reset(this, classFile);
-               
                codeStream.initializeMaxLocals(dispatchBinding);
-               
+
+               Argument[] itdArgs = this.arguments;
+               if (itdArgs != null) {
+                       for (int a = 0; a < itdArgs.length; a++) {
+                               LocalVariableBinding lvb = itdArgs[a].binding;
+                               LocalVariableBinding lvbCopy = new LocalVariableBinding(lvb.name, lvb.type, lvb.modifiers, true);
+                               codeStream.record(lvbCopy);
+                               lvbCopy.recordInitializationStartPC(0);
+                               lvbCopy.resolvedPosition = lvb.resolvedPosition;
+                       }
+               }
+
                MethodBinding methodBinding = introducedMethod;
                TypeBinding[] parameters = methodBinding.parameters;
                int length = parameters.length;
@@ -276,11 +288,11 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
                        else
                                resolvedPosition++;
                }
-//             TypeBinding type;
+               // TypeBinding type;
                if (methodBinding.isStatic())
                        codeStream.invokestatic(methodBinding);
                else {
-                       if (methodBinding.declaringClass.isInterface()){
+                       if (methodBinding.declaringClass.isInterface()) {
                                codeStream.invokeinterface(methodBinding);
                        } else {
                                codeStream.invokevirtual(methodBinding);
@@ -288,23 +300,28 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
                }
                AstUtil.generateReturn(dispatchBinding.returnType, codeStream);
 
+               // tag the local variables as used throughout the method
+               if (itdArgs != null) {
+                       for (int a = 0; a < itdArgs.length; a++) {
+                               codeStream.locals[a].recordInitializationEndPC(codeStream.position);
+                       }
+               }
                classFile.completeCodeAttribute(codeAttributeOffset);
                attributeNumber++;
                classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
        }
 
-       
        protected Shadow.Kind getShadowKindForBody() {
                return Shadow.MethodExecution;
        }
-       
+
        // XXX this code is copied from MethodScope, with a few adjustments for ITDs...
        private void checkAndSetModifiersForMethod() {
-               
+
                // for reported problems, we want the user to see the declared selector
                char[] realSelector = this.selector;
                this.selector = declaredSelector;
-               
+
                final ReferenceBinding declaringClass = this.binding.declaringClass;
                if ((declaredModifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
                        scope.problemReporter().duplicateModifierForMethod(onTypeBinding, this);
@@ -314,14 +331,16 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
 
                // check for abnormal modifiers
                int unexpectedModifiers = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected
-                       | ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp);
+                               | ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal
+                               | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp);
                if ((realModifiers & unexpectedModifiers) != 0) {
                        scope.problemReporter().illegalModifierForMethod(this);
                        declaredModifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~unexpectedModifiers;
                }
 
                // check for incompatible modifiers in the visibility bits, isolate the visibility bits
-               int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
+               int accessorBits = realModifiers
+                               & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
                if ((accessorBits & (accessorBits - 1)) != 0) {
                        scope.problemReporter().illegalVisibilityModifierCombinationForMethod(onTypeBinding, this);
 
@@ -338,18 +357,18 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
 
                // check for modifiers incompatible with abstract modifier
                if ((declaredModifiers & ClassFileConstants.AccAbstract) != 0) {
-                       int incompatibleWithAbstract = ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp;
+                       int incompatibleWithAbstract = ClassFileConstants.AccStatic | ClassFileConstants.AccFinal
+                                       | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp;
                        if ((declaredModifiers & incompatibleWithAbstract) != 0)
                                scope.problemReporter().illegalAbstractModifierCombinationForMethod(onTypeBinding, this);
                        if (!onTypeBinding.isAbstract())
                                scope.problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) onTypeBinding, this);
                }
 
-               /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
-               // methods from a final class are final : 8.4.3.3 
-               if (methodBinding.declaringClass.isFinal())
-                       modifiers |= AccFinal;
-               */
+               /*
+                * DISABLED for backward compatibility with javac (if enabled should also mark private methods as final) // methods from a
+                * final class are final : 8.4.3.3 if (methodBinding.declaringClass.isFinal()) modifiers |= AccFinal;
+                */
                // native methods cannot also be tagged as strictfp
                if ((declaredModifiers & ClassFileConstants.AccNative) != 0 && (declaredModifiers & ClassFileConstants.AccStrictfp) != 0)
                        scope.problemReporter().nativeMethodsCannotBeStrictfp(onTypeBinding, this);
@@ -359,6 +378,6 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
                        scope.problemReporter().unexpectedStaticModifierForMethod(onTypeBinding, this);
 
                // restore the true selector now that any problems have been reported
-               this.selector = realSelector;           
+               this.selector = realSelector;
        }
 }