diff options
author | acolyer <acolyer> | 2005-09-05 14:10:13 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-09-05 14:10:13 +0000 |
commit | ee6a87405375a518c4e7cd73c8ce856145de7c1d (patch) | |
tree | 591967b824479f1878758b172208f4b6d3bc984b /org.aspectj.ajdt.core | |
parent | a905c8e46f43684ef19adc4817374b82f2b0993d (diff) | |
download | aspectj-ee6a87405375a518c4e7cd73c8ce856145de7c1d.tar.gz aspectj-ee6a87405375a518c4e7cd73c8ce856145de7c1d.zip |
fix for pr87530, final modifier on interface itdm
Diffstat (limited to 'org.aspectj.ajdt.core')
6 files changed, 100 insertions, 18 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 a56f2a161..666335db7 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 @@ -63,6 +63,10 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { protected char[] getPrefix() { return (NameMangler.ITD_PREFIX + "interMethod$").toCharArray(); } + + public boolean isFinal() { + return (declaredModifiers & AccFinal) != 0; + } public void analyseCode( ClassScope currentScope, diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index 4bd5cd7be..32dd4c188 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -384,7 +384,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC for (Iterator i = mungers.iterator(); i.hasNext(); ) { ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); EclipseTypeMunger munger = factory.makeEclipseTypeMunger(m); - if (munger.munge(sourceType)) { + if (munger.munge(sourceType,onType)) { if (onType.isInterface() && munger.getMunger().needsAccessToTopmostImplementor()) { @@ -509,7 +509,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC for (Iterator i = onType.getInterTypeMungers().iterator(); i.hasNext();) { EclipseTypeMunger munger = (EclipseTypeMunger) i.next(); //System.out.println("applying: " + munger + " to " + new String(sourceType.sourceName)); - munger.munge(sourceType); + munger.munge(sourceType,onType); } // Call if you would like to do source weaving of declare @method/@constructor diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java index 038d92d22..e499f2df5 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java @@ -17,6 +17,7 @@ import java.lang.reflect.Modifier; import org.aspectj.bridge.ISourceLocation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.aspectj.org.eclipse.jdt.internal.compiler.env.IConstants; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; @@ -24,6 +25,7 @@ import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.NewConstructorTypeMunger; import org.aspectj.weaver.NewFieldTypeMunger; import org.aspectj.weaver.NewMethodTypeMunger; +import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.ResolvedTypeMunger; @@ -70,17 +72,29 @@ public class EclipseTypeMunger extends ConcreteTypeMunger { * Modifies signatures of a TypeBinding through its ClassScope, * i.e. adds Method|FieldBindings, plays with inheritance, ... */ - public boolean munge(SourceTypeBinding sourceType) { - ResolvedType rt = world.fromEclipse(sourceType); + public boolean munge(SourceTypeBinding sourceType, ResolvedType onType) { + ResolvedType rt = onType; if (rt.isRawType() || rt.isParameterizedType()) rt = rt.getGenericType(); - if (!rt.equals(targetTypeX)) return false; //??? move this test elsewhere + boolean isExactTargetType = rt.equals(targetTypeX); + if (!isExactTargetType) { + // might be the topmost implementor of an interface we care about + if (munger.getKind() != ResolvedTypeMunger.Method) return false; + if (onType.isInterface()) return false; + if (!munger.needsAccessToTopmostImplementor()) return false; + // so we do need access, and this type could be it... + if (!onType.isTopmostImplementor(targetTypeX)) return false; + // we are the topmost implementor of an interface type that needs munging + // but we only care about public methods here (we only do this at all to + // drive the JDT MethodVerifier correctly) + if (!Modifier.isPublic(munger.getSignature().getModifiers())) return false; + } //System.out.println("munging: " + sourceType); // System.out.println("match: " + world.fromEclipse(sourceType) + // " with " + targetTypeX); if (munger.getKind() == ResolvedTypeMunger.Field) { mungeNewField(sourceType, (NewFieldTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.Method) { - mungeNewMethod(sourceType, (NewMethodTypeMunger)munger); + return mungeNewMethod(sourceType, onType, (NewMethodTypeMunger)munger, isExactTargetType); } else if (munger.getKind() == ResolvedTypeMunger.Constructor) { mungeNewConstructor(sourceType, (NewConstructorTypeMunger)munger); } else { @@ -90,18 +104,39 @@ public class EclipseTypeMunger extends ConcreteTypeMunger { } - private void mungeNewMethod(SourceTypeBinding sourceType, NewMethodTypeMunger munger) { -// if (shouldTreatAsPublic()) { -// MethodBinding binding = world.makeMethodBinding(munger.getSignature()); -// findOrCreateInterTypeMemberFinder(classScope).addInterTypeMethod(binding); -// //classScope.referenceContext.binding.addMethod(binding); -// } else { - InterTypeMethodBinding binding = - new InterTypeMethodBinding(world, munger.getSignature(), aspectType, sourceMethod); - findOrCreateInterTypeMemberFinder(sourceType).addInterTypeMethod(binding); -// } + private boolean mungeNewMethod(SourceTypeBinding sourceType, ResolvedType onType, NewMethodTypeMunger munger, boolean isExactTargetType) { + InterTypeMethodBinding binding = + new InterTypeMethodBinding(world, munger.getSignature(), aspectType, sourceMethod); + if (!isExactTargetType) { + // we're munging an interface ITD onto a topmost implementor + ResolvedMember existingMember = onType.lookupMemberIncludingITDsOnInterfaces(getSignature()); + if (existingMember != null) { + // already have an implementation, so don't do anything + if (onType == existingMember.getDeclaringType() && Modifier.isFinal(munger.getSignature().getModifiers())) { + // final modifier on default implementation is taken to mean that + // no-one else can provide an implementation + MethodBinding offendingBinding = sourceType.getExactMethod(binding.selector, binding.parameters, sourceType.scope.compilationUnitScope()); + sourceType.scope.problemReporter().finalMethodCannotBeOverridden(offendingBinding, binding); + } + // so that we find methods from our superinterfaces later on... + findOrCreateInterTypeMemberFinder(sourceType); + return false; + } + } + + // retain *only* the visibility modifiers and abstract when putting methods on an interface... + if (sourceType.isInterface()) { + boolean isAbstract = (binding.modifiers & IConstants.AccAbstract) != 0; + binding.modifiers = (binding.modifiers & (IConstants.AccPublic | IConstants.AccProtected | IConstants.AccPrivate)); + if (isAbstract) binding.modifiers |= IConstants.AccAbstract; + } + + findOrCreateInterTypeMemberFinder(sourceType).addInterTypeMethod(binding); + return true; } + + private void mungeNewConstructor(SourceTypeBinding sourceType, NewConstructorTypeMunger munger) { if (shouldTreatAsPublic()) { MethodBinding binding = world.makeMethodBinding(munger.getSignature()); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java index db7e8131e..e69e40978 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMemberFinder.java @@ -14,8 +14,10 @@ package org.aspectj.ajdt.internal.compiler.lookup; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; @@ -242,9 +244,11 @@ public class InterTypeMemberFinder implements IMemberFinder { // return m2.declaringClass; // } + // find all of my methods, including ITDs + // PLUS: any public ITDs made on interfaces that I implement public MethodBinding[] methods(SourceTypeBinding sourceTypeBinding) { MethodBinding[] orig = sourceTypeBinding.methods(); - if (interTypeMethods.isEmpty()) return orig; +// if (interTypeMethods.isEmpty()) return orig; List ret = new ArrayList(Arrays.asList(orig)); for (int i=0, len=interTypeMethods.size(); i < len; i++) { @@ -252,10 +256,34 @@ public class InterTypeMemberFinder implements IMemberFinder { ret.add(method); } + ReferenceBinding [] interfaces = sourceTypeBinding.superInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + if (interfaces[i] instanceof SourceTypeBinding) { + SourceTypeBinding intSTB = (SourceTypeBinding) interfaces[i]; + addPublicITDSFrom(intSTB,ret); + } + } + if (ret.isEmpty()) return SourceTypeBinding.NoMethods; return (MethodBinding[])ret.toArray(new MethodBinding[ret.size()]); } + private void addPublicITDSFrom(SourceTypeBinding anInterface,List toAList) { + if (anInterface.memberFinder != null) { + InterTypeMemberFinder finder = (InterTypeMemberFinder) anInterface.memberFinder; + for (Iterator iter = finder.interTypeMethods.iterator(); iter.hasNext();) { + MethodBinding aBinding = (MethodBinding) iter.next(); + if (Modifier.isPublic(aBinding.modifiers)) { + toAList.add(aBinding); + } + } + } + ReferenceBinding superType = anInterface.superclass; + if (superType instanceof SourceTypeBinding && superType.isInterface()) { + addPublicITDSFrom((SourceTypeBinding)superType,toAList); + } + } + //XXX conflicts public MethodBinding[] getMethods( SourceTypeBinding sourceTypeBinding, diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java index 290c9ee15..658b6ef13 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeMethodBinding.java @@ -17,6 +17,7 @@ import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.Member; import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.UnresolvedType; +import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.InvocationSite; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; @@ -128,7 +129,11 @@ public class InterTypeMethodBinding extends MethodBinding { return false; } - + public boolean isFinal() { + if (sourceMethod == null || !(sourceMethod instanceof InterTypeMethodDeclaration)) return super.isFinal(); + return ((InterTypeMethodDeclaration)sourceMethod).isFinal(); + } + public MethodBinding getAccessMethod(boolean staticReference) { if (staticReference) return postDispatchMethod; else return syntheticMethod; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java index 34028b337..421286af1 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java @@ -412,4 +412,14 @@ public class AjProblemReporter extends ProblemReporter { if (!(methodDecl instanceof PointcutDeclaration)) super.unusedPrivateMethod(methodDecl); } + + /** + * A side-effect of the way that we handle itds on default methods on top-most implementors + * of interfaces is that a class acquiring a final default ITD will erroneously report + * that it can't override its own member. This method detects that situation. + */ + public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBinding inheritedMethod) { + if (currentMethod == inheritedMethod) return; + super.finalMethodCannotBeOverridden(currentMethod, inheritedMethod); + } } |