diff options
author | aclement <aclement> | 2009-01-29 05:59:33 +0000 |
---|---|---|
committer | aclement <aclement> | 2009-01-29 05:59:33 +0000 |
commit | 9a29070066af5b98dd3a155c51f3de1e15d4c58b (patch) | |
tree | a07f62053aeec4f9387f0c1ec9f63ec849ca50c7 /org.aspectj.ajdt.core | |
parent | ca925703db97ea3de19067e1f742f34707830954 (diff) | |
download | aspectj-9a29070066af5b98dd3a155c51f3de1e15d4c58b.tar.gz aspectj-9a29070066af5b98dd3a155c51f3de1e15d4c58b.zip |
194314: now copies the parameter names from the ITD to the dispatcher
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r-- | org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java | 253 |
1 files changed, 136 insertions, 117 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java index cedc82c4d..d0dffa682 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java @@ -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; } } |