diff options
author | aclement <aclement> | 2005-08-23 14:02:30 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-08-23 14:02:30 +0000 |
commit | 284c4eed6b80ac368ca60c2f9eb7aff1234bf2a8 (patch) | |
tree | 0953fe63aa97f0b16f8358ed0f3eee18bfb5db13 /org.aspectj.ajdt.core | |
parent | 4aacf20ad0fd3f3782fe1ff936aa13f666431beb (diff) | |
download | aspectj-284c4eed6b80ac368ca60c2f9eb7aff1234bf2a8.tar.gz aspectj-284c4eed6b80ac368ca60c2f9eb7aff1234bf2a8.zip |
@override support for ITDs. Plus some binary weaving generic ITD tests.
Diffstat (limited to 'org.aspectj.ajdt.core')
2 files changed, 103 insertions, 0 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 cac14243d..80271fbdf 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 @@ -17,6 +17,7 @@ import java.lang.reflect.Modifier; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; 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.CompilationUnitDeclaration; @@ -26,6 +27,8 @@ 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.MethodBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; @@ -83,6 +86,8 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { super.resolve(upperScope); } + + public void resolveStatements() { if ((modifiers & AccSemicolonBody) != 0) { if ((declaredModifiers & AccAbstract) == 0) @@ -93,6 +98,45 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { scope.problemReporter().methodNeedingNoBody(this); } + // check @Override annotation - based on MethodDeclaration.resolveStatements() @Override processing + checkOverride: { + if (this.binding == null) break checkOverride; + if (this.scope.compilerOptions().sourceLevel < JDK1_5) break checkOverride; + int bindingModifiers = this.binding.modifiers; + 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()); + + boolean reportError = true; + // Go up the hierarchy, looking for something we override + ReferenceBinding supertype = onTypeBinding.superclass(); + 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; + else { + for (int j = 0; j < mb.parameters.length && couldBeMatch; j++) { + 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; + } + 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 (!Modifier.isAbstract(declaredModifiers)) super.resolveStatements(); if (Modifier.isStatic(declaredModifiers)) { 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 bd3783b0a..7a7f54318 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 @@ -31,6 +31,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; 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; @@ -313,5 +314,63 @@ public class AjProblemReporter extends ProblemReporter { methodDecl.sourceEnd,this.referenceContext, this.referenceContext == null ? null : this.referenceContext.compilationResult()); } + + + /** + * Called when there is an ITD marked @override that doesn't override a supertypes method. + * The method and the binding are passed - some information is useful from each. The 'method' + * knows about source offsets for the message, the 'binding' has the signature of what the + * ITD is trying to be in the target class. + */ + public void itdMethodMustOverride(AbstractMethodDeclaration method,MethodBinding binding) { + this.handle( + IProblem.MethodMustOverride, + new String[] {new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, false), new String(binding.declaringClass.readableName()), }, + new String[] {new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, true), new String(binding.declaringClass.shortReadableName()),}, + method.sourceStart, + method.sourceEnd, + this.referenceContext, + this.referenceContext == null ? null : this.referenceContext.compilationResult()); + } + + /** + * Overrides the implementation in ProblemReporter and is ITD aware. + * To report a *real* problem with an ITD marked @override, the other methodMustOverride() method is used. + */ + public void methodMustOverride(AbstractMethodDeclaration method) { + MethodBinding binding = method.binding; + + // ignore ajc$ methods + if (new String(method.selector).startsWith("ajc$")) return; + + ResolvedType onTypeX = factory.fromEclipse(method.binding.declaringClass); + for (Iterator i = onTypeX.getInterTypeMungersIncludingSupers().iterator(); i.hasNext(); ) { + ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); + ResolvedMember sig = m.getSignature(); + if (ResolvedType.matches(AjcMemberMaker.interMethod(sig,m.getAspectType(), + sig.getDeclaringType().resolve(factory.getWorld()).isInterface()), + factory.makeResolvedMember(method.binding))) { + // match, so dont need to report a problem! + return; + } + } + // report the error... + super.methodMustOverride(method); + } + + + private String typesAsString(boolean isVarargs, TypeBinding[] types, boolean makeShort) { + StringBuffer buffer = new StringBuffer(10); + for (int i = 0, length = types.length; i < length; i++) { + if (i != 0) + buffer.append(", "); //$NON-NLS-1$ + TypeBinding type = types[i]; + boolean isVarargType = isVarargs && i == length-1; + if (isVarargType) type = ((ArrayBinding)type).elementsType(); + buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName())); + if (isVarargType) buffer.append("..."); //$NON-NLS-1$ + } + return buffer.toString(); + } } |