From b17970f20c9040c3455a02b353a8e7fbc1914024 Mon Sep 17 00:00:00 2001 From: aclement Date: Sun, 4 Dec 2005 13:40:06 +0000 Subject: [PATCH] fixes for 117882 --- .../compiler/lookup/AjLookupEnvironment.java | 57 +++++++++++++ .../org/aspectj/weaver/FakeAnnotation.java | 81 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 weaver/src/org/aspectj/weaver/FakeAnnotation.java 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 e743af75e..966f2c564 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 @@ -54,8 +54,10 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; 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.problem.ProblemReporter; +import org.aspectj.weaver.AnnotationX; import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.ConcreteTypeMunger; +import org.aspectj.weaver.FakeAnnotation; import org.aspectj.weaver.ReferenceType; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.TypeVariable; @@ -726,6 +728,9 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC } TypeBinding tb = factory.makeTypeBinding(aspectType); + + + // TODO asc determine if there really is a problem here (see comment below) // ClassCastException here means we probably have either a parameterized type or a raw type, we need the @@ -739,6 +744,54 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC Annotation[] toAdd = methodDecl.annotations; // this is what to add abits = toAdd[0].resolvedType.getAnnotationTagBits(); + if (sourceType instanceof BinaryTypeBinding) { + // In this case we can't access the source type binding to add a new annotation, so let's put something + // on the weaver type temporarily + ResolvedType theTargetType = factory.fromEclipse(sourceType); + TypeBinding theAnnotationType = toAdd[0].resolvedType; + String name = new String(theAnnotationType.qualifiedPackageName())+"."+new String(theAnnotationType.sourceName()); + String sig = new String(theAnnotationType.signature()); + if (theTargetType.hasAnnotation(UnresolvedType.forSignature(sig))) { + CompilationAndWeavingContext.leavingPhase(tok); + return false; + } + + // FIXME asc tidy up this code that duplicates whats below! + // Simple checks on the bits + boolean giveupnow = false; + if (((abits & TagBits.AnnotationTargetMASK)!=0)) { + if ( isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(abits)) { + // error will have been already reported + giveupnow = true; + } else if ( (sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType)==0) || + (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType)==0) ) { + + if (reportProblems) { + if (decA.isExactPattern()) { + factory.showMessage(IMessage.ERROR, + WeaverMessages.format(WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION,rtx.getName(),toAdd[0].type,stringifyTargets(abits)), + decA.getSourceLocation(), null); + } + // dont put out the lint - the weaving process will do that +// else { +// if (factory.getWorld().getLint().invalidTargetForAnnotation.isEnabled()) { +// factory.getWorld().getLint().invalidTargetForAnnotation.signal(new String[]{rtx.getName(),toAdd[0].type.toString(),stringifyTargets(abits)},decA.getSourceLocation(),null); +// } +// } + } + giveupnow=true; + } + } + if (giveupnow) { + CompilationAndWeavingContext.leavingPhase(tok); + return false; + } + + theTargetType.addAnnotation(new AnnotationX(new FakeAnnotation(name,sig,(abits & TagBits.AnnotationRuntimeRetention)!=0),factory.getWorld())); + CompilationAndWeavingContext.leavingPhase(tok); + return true; + } + Annotation currentAnnotations[] = sourceType.scope.referenceContext.annotations; if (currentAnnotations!=null) for (int i = 0; i < currentAnnotations.length; i++) { @@ -797,6 +850,10 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC CompilationAndWeavingContext.leavingPhase(tok); return true; } + + private boolean isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(long abits) { + return (abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType))==0; + } private void reportDeclareParentsMessage(WeaveMessage.WeaveMessageKind wmk,SourceTypeBinding sourceType,ResolvedType parent) { diff --git a/weaver/src/org/aspectj/weaver/FakeAnnotation.java b/weaver/src/org/aspectj/weaver/FakeAnnotation.java new file mode 100644 index 000000000..ea36cea30 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/FakeAnnotation.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * initial implementation Andy Clement + *******************************************************************************/ +package org.aspectj.weaver; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.annotation.Annotation; +import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair; + +/** + * For implementing declare @type interacting with declare @parents during compilation - we need to be + * able to add an annotation to 'binary type binding' (this is how types are seen during incremental compilation). + * Unlike a SourceTypeBinding - a BinaryTypeBinding does not allow easy interaction with its annotations - + * so what we do is take the eclipse annotation, suck out the name/signature and visibility and put that information + * in a 'FakeAnnotation'. The FakeAnnotation is attached to the BCEL delegate for the binary type binding - + * this will allow type resolution to succeed correctly. The FakeAnnotation never makes it to disk, since the weaver + * does the job properly, attaching a real annotation. + */ +public class FakeAnnotation extends Annotation { + + private String name; + private String sig; + private boolean isRuntimeVisible; + + public FakeAnnotation(String name,String sig,boolean isRuntimeVisible) { + super(0,null,true); + this.name = name; + this.sig = sig; + this.isRuntimeVisible = isRuntimeVisible; + } + + public String getTypeName() { + return name; + } + + public String getTypeSignature() { + return sig; + } + + public void addElementNameValuePair(ElementNameValuePair evp) { + // doesnt need to know about name/value pairs + } + + protected void dump(DataOutputStream dos) throws IOException { + // should be serialized + } + + public int getTypeIndex() { + return 0; + } + + public List getValues() { + return null; + } + + public boolean isRuntimeVisible() { + return isRuntimeVisible; + } + + protected void isRuntimeVisible(boolean b) { + } + + public String toShortString() { + return "@"+this.name; + } + + public String toString() { + return this.name; + } +} -- 2.39.5