diff options
author | acolyer <acolyer> | 2005-02-17 12:58:24 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-02-17 12:58:24 +0000 |
commit | b4574b90b2db6cdae830e702825d86957447c3b9 (patch) | |
tree | d93001dbf1804933f64350dbd52bc1ced5402e7c | |
parent | db5e1868bb553bad01441e70db166ac4429de2f2 (diff) | |
download | aspectj-b4574b90b2db6cdae830e702825d86957447c3b9.tar.gz aspectj-b4574b90b2db6cdae830e702825d86957447c3b9.zip |
support for annotations on ITDs, and declare annotation
23 files changed, 605 insertions, 5 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareAnnotationDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareAnnotationDeclaration.java new file mode 100644 index 000000000..7e4edec32 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareAnnotationDeclaration.java @@ -0,0 +1,52 @@ +/* ******************************************************************* + * Copyright (c) 2005 IBM Corporation. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Adrian Colyer initial implementation + * ******************************************************************/ + +package org.aspectj.ajdt.internal.compiler.ast; + +import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.aspectj.weaver.patterns.DeclareAnnotation; + +public class DeclareAnnotationDeclaration extends DeclareDeclaration { + private Annotation annotation; + + public DeclareAnnotationDeclaration(CompilationResult result, DeclareAnnotation symbolicDeclare, Annotation annotation) { + super(result,symbolicDeclare); + this.annotation = annotation; + addAnnotation(annotation); + symbolicDeclare.setAnnotationString(annotation.toString()); + symbolicDeclare.setAnnotationMethod(new String(selector)); + } + + public Annotation getDeclaredAnnotation() { + return annotation; + } + + /* (non-Javadoc) + * @see org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration#shouldDelegateCodeGeneration() + */ + protected boolean shouldDelegateCodeGeneration() { + return true; // declare annotation needs a method to be written out. + } + + private void addAnnotation(Annotation ann) { + if (this.annotations == null) { + this.annotations = new Annotation[1]; + } else { + Annotation[] old = this.annotations; + this.annotations = new Annotation[old.length + 1]; + System.arraycopy(old,0,this.annotations,1,old.length); + } + this.annotations[0] = ann; + } + +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java index f869259c8..8796a3409 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/DeclareDeclaration.java @@ -48,14 +48,23 @@ public class DeclareDeclaration extends AjMethodDeclaration { /** - * A pointcut declaration exists in a classfile only as an attibute on the + * A declare declaration exists in a classfile only as an attibute on the * class. Unlike advice and inter-type declarations, it has no corresponding * method. + * **AMC** changed the above policy in the case of declare annotation, which uses a + * corresponding method as the anchor for the declared annotation */ public void generateCode(ClassScope classScope, ClassFile classFile) { classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.DeclareAttribute(declareDecl))); + if (shouldDelegateCodeGeneration()) { + super.generateCode(classScope,classFile); + } return; } + + protected boolean shouldDelegateCodeGeneration() { + return false; + } public void parseStatements( Parser parser, diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java index 4644f75d5..be4baf0d5 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PseudoTokens.java @@ -139,6 +139,17 @@ public class PseudoTokens extends ASTNode { } } + public Declare parseAnnotationDeclare(Parser parser) { + PatternParser patternParser = new PatternParser(tokenSource); + try { + Declare ret = patternParser.parseDeclareAnnotation(); + checkEof(parser); + return ret; + } catch (ParserException pe) { + reportError(parser, pe); + return null; + } } + public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { for (int i=0, len=tokens.length; i < len; i++) { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java index 4ec365b8e..c3c766b9e 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/InterTypeFieldBinding.java @@ -100,7 +100,6 @@ public class InterTypeFieldBinding extends FieldBinding { return false; } - public SyntheticMethodBinding getAccessMethod(boolean isReadAccess) { if (isReadAccess) return reader; else return writer; 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 39d780947..f3abe8dea 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 @@ -56,7 +56,7 @@ public class InterTypeMethodBinding extends MethodBinding { } - + //XXX this is identical to InterTypeFieldBinding public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { scope.compilationUnitScope().recordTypeReference(declaringClass); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/DeclarationFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/DeclarationFactory.java index d9f557afe..250e791f0 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/DeclarationFactory.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/parser/DeclarationFactory.java @@ -16,6 +16,7 @@ import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration; import org.aspectj.ajdt.internal.compiler.ast.AjConstructorDeclaration; import org.aspectj.ajdt.internal.compiler.ast.AjMethodDeclaration; import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration; +import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration; import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration; import org.aspectj.ajdt.internal.compiler.ast.IfPseudoToken; import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration; @@ -30,8 +31,10 @@ import org.aspectj.ajdt.internal.compiler.ast.PseudoTokens; import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; import org.aspectj.weaver.AdviceKind; import org.aspectj.weaver.patterns.Declare; +import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; @@ -200,6 +203,17 @@ public class DeclarationFactory implements IDeclarationFactory { } /* (non-Javadoc) + * @see org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser.IDeclarationFactory#createDeclareAnnotationDeclaration(org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult, org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode, org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation, org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser) + */ + public MethodDeclaration createDeclareAnnotationDeclaration( + CompilationResult result, ASTNode pseudoTokens, + Annotation annotation, Parser parser) { + DeclareAnnotation declare = (DeclareAnnotation) ((PseudoTokens)pseudoTokens).parseAnnotationDeclare(parser); + DeclareAnnotationDeclaration decl = new DeclareAnnotationDeclaration(result,declare,annotation); + return decl; + } + + /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.parser.Parser.IDeclarationFactory#createInterTypeFieldDeclaration(org.eclipse.jdt.internal.compiler.CompilationResult, org.eclipse.jdt.internal.compiler.ast.TypeReference) */ public MethodDeclaration createInterTypeFieldDeclaration(CompilationResult result, TypeReference onType) { 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 9a6e11857..63648a82f 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 @@ -26,12 +26,15 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.aspectj.org.eclipse.jdt.internal.compiler.IProblemFactory; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +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.Binding; 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; +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.util.FuzzyBoolean; @@ -216,6 +219,30 @@ public class AjProblemReporter extends ProblemReporter { super.abstractMethodMustBeImplemented(type, abstractMethod); } + /* (non-Javadoc) + * @see org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter#disallowedTargetForAnnotation(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation) + */ + public void disallowedTargetForAnnotation(Annotation annotation) { + // if the annotation's recipient is an ITD, it might be allowed after all... + if (annotation.recipient instanceof MethodBinding) { + MethodBinding binding = (MethodBinding) annotation.recipient; + String name = new String(binding.selector); + if (name.startsWith("ajc$")) { + long metaTagBits = annotation.resolvedType.getAnnotationTagBits(); // could be forward reference + if (name.indexOf("interField") != -1) { + if ((metaTagBits & TagBits.AnnotationForField) != 0) return; + } else if (name.indexOf("InterConstructor") != -1) { + if ((metaTagBits & TagBits.AnnotationForConstructor) != 0) return; + } else if (name.indexOf("interMethod") != -1) { + if ((metaTagBits & TagBits.AnnotationForMethod) != 0) return; + } + } + } + + // not our special case, report the problem... + super.disallowedTargetForAnnotation(annotation); + } + public void handle( int problemId, String[] problemArguments, diff --git a/tests/java5/annotations/aspectMembers/a/AnnotatedAspect.aj b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect.aj new file mode 100644 index 000000000..03165b105 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect.aj @@ -0,0 +1,23 @@ +package a; + +@TypeAnnotation +public aspect AnnotatedAspect { + + @FieldAnnotation int foo = 5; + + @MethodAnnotation int getFoo() { return foo; } + + @ConstructorAnnotation + public AnnotatedAspect() {} + +} + +aspect VerifyAnnotations { + + declare warning : set(@FieldAnnotation * *) : "annotated field"; + declare warning : execution(@MethodAnnotation * *(..)) : "annotated method"; + declare warning : execution(@ConstructorAnnotation new(..)) : "annotated constructor"; + declare warning : staticinitialization(@TypeAnnotation *) : "annotated type"; + + +}
\ No newline at end of file diff --git a/tests/java5/annotations/aspectMembers/a/AnnotatedAspect02.aj b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect02.aj new file mode 100644 index 000000000..d92dc33b1 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect02.aj @@ -0,0 +1,22 @@ +package a; + +@MethodAnnotation +public aspect AnnotatedAspect02 { + + @TypeAnnotation int goo; + + @FieldAnnotation int getGoo() { return goo; } + + @AnnotationAnnotation AnnotatedAspect02() { goo = 5; } + +} + +aspect VerifyAnnotations { + + declare warning : set(@FieldAnnotation * *) : "annotated field"; + declare warning : execution(@MethodAnnotation * *(..)) : "annotated method"; + declare warning : execution(@ConstructorAnnotation new(..)) : "annotated constructor"; + declare warning : staticinitialization(@TypeAnnotation *) : "annotated type"; + + +}
\ No newline at end of file diff --git a/tests/java5/annotations/aspectMembers/a/AnnotatedAspect03.aj b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect03.aj new file mode 100644 index 000000000..939285816 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect03.aj @@ -0,0 +1,26 @@ +package a; + +@TypeAnnotation +public aspect AnnotatedAspect03 { + + @FieldAnnotation int foo = 5; + + @FieldAnnotation private int ITDMe.goo = 3; + + @MethodAnnotation private int ITDMe.getGoo() { return goo; } + + @ConstructorAnnotation public ITDMe.new(int x) { goo = x; } + +} + +class ITDMe {} + +aspect VerifyAnnotations { + + declare warning : set(@FieldAnnotation * *) : "annotated field"; + declare warning : execution(@MethodAnnotation * *(..)) : "annotated method"; + declare warning : execution(@ConstructorAnnotation new(..)) : "annotated constructor"; + declare warning : staticinitialization(@TypeAnnotation *) : "annotated type"; + + +}
\ No newline at end of file diff --git a/tests/java5/annotations/aspectMembers/a/AnnotatedAspect04.aj b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect04.aj new file mode 100644 index 000000000..c19b057a3 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/AnnotatedAspect04.aj @@ -0,0 +1,15 @@ +package a; + +@TypeAnnotation +public aspect AnnotatedAspect04 { + + @ConstructorAnnotation private int ITDMe.goo = 3; + + @FieldAnnotation private int ITDMe.getGoo() { return goo; } + + @TypeAnnotation public ITDMe.new(int x) { goo = x; } + + @MethodAnnotation int ITDMe.foo = 2; // known limitation - no warning +} + +class ITDMe {} diff --git a/tests/java5/annotations/aspectMembers/a/Annotations.java b/tests/java5/annotations/aspectMembers/a/Annotations.java new file mode 100644 index 000000000..21a0bb1a7 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/Annotations.java @@ -0,0 +1,29 @@ +package a; + +import java.lang.annotation.*; + +@Target(ElementType.ANNOTATION_TYPE) +@interface AnnotationAnnotation {} + +@Target(ElementType.CONSTRUCTOR) +@interface ConstructorAnnotation {} + +@Target(ElementType.FIELD) +@interface FieldAnnotation {} + +@Target(ElementType.LOCAL_VARIABLE) +@interface LocalVarAnnotation {} + +@Target(ElementType.METHOD) +@interface MethodAnnotation {} + +@Target(ElementType.PACKAGE) +@interface PackageAnnotation {} + +@Target(ElementType.PARAMETER) +@interface ParameterAnnotation {} + +@Target(ElementType.TYPE) +@interface TypeAnnotation {} + +@interface AnyAnnotation {}
\ No newline at end of file diff --git a/tests/java5/annotations/aspectMembers/a/Foo.java b/tests/java5/annotations/aspectMembers/a/Foo.java new file mode 100644 index 000000000..3fd621e26 --- /dev/null +++ b/tests/java5/annotations/aspectMembers/a/Foo.java @@ -0,0 +1,17 @@ +package a; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +@TypeAnnotation +public class Foo { + + @FieldAnnotation int foo; + + @MethodAnnotation int getFoo() { return foo; } + + @MethodAnnotation int goo; +} diff --git a/tests/java5/annotations/declare/BasicParseTest.aj b/tests/java5/annotations/declare/BasicParseTest.aj new file mode 100644 index 000000000..5c3eca249 --- /dev/null +++ b/tests/java5/annotations/declare/BasicParseTest.aj @@ -0,0 +1,15 @@ +public aspect BasicParseTest { + + declare warning : set(* *) : "setting"; + + declare @field: * foo : @MyAnnotation; + + declare @method: * foo() : @MyAnnotation; + + declare @constructor: Foo*.new(..) : @MyAnnotation; + + declare @type: org.xyz..* : @MyAnnotation; + +} + +@interface MyAnnotation {}
\ No newline at end of file diff --git a/tests/java5/pseudoKeywords/MethodCalledAround.java b/tests/java5/pseudoKeywords/MethodCalledAround.java new file mode 100644 index 000000000..799b5b197 --- /dev/null +++ b/tests/java5/pseudoKeywords/MethodCalledAround.java @@ -0,0 +1,3 @@ +public class MethodCalledAround { + void around() { ; } +}
\ No newline at end of file diff --git a/tests/java5/pseudoKeywords/MethodCalledAroundAspect.java b/tests/java5/pseudoKeywords/MethodCalledAroundAspect.java new file mode 100644 index 000000000..d20bc7bce --- /dev/null +++ b/tests/java5/pseudoKeywords/MethodCalledAroundAspect.java @@ -0,0 +1,3 @@ +public aspect MethodCalledAroundAspect { + void around() { ; } +}
\ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java b/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java index 4d9aaba79..9f83d703f 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java @@ -45,6 +45,14 @@ public class Ajc150Tests extends org.aspectj.testing.XMLBasedAjcTestCase { } } + public void test_aroundMethod() { + runTest("method called around in class"); + } + + public void test_aroundMethodAspect() { + runTest("method called around in aspect"); + } + public void test_ambiguousBindingsDetection() { runTest("Various kinds of ambiguous bindings"); } diff --git a/tests/src/org/aspectj/systemtest/ajc150/Annotations.java b/tests/src/org/aspectj/systemtest/ajc150/Annotations.java index 1ac7ef36e..d242697bf 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/Annotations.java +++ b/tests/src/org/aspectj/systemtest/ajc150/Annotations.java @@ -60,6 +60,48 @@ public class Annotations extends XMLBasedAjcTestCase { } } + public void testAnnotatedAnnotations() { + runTest("annotated annotations (@Target)"); + } + + public void testSimpleAnnotatedAspectMembers() { + runTest("simple annotated aspect members"); + } + + public void testAnnotatedAspectMembersWithWrongAnnotationType() { + runTest("simple annotated aspect members with bad target"); + } + + // more implementation work needed before this test passes +// public void testAnnotatedITDs() { +// runTest("annotated itds"); +// } + + public void testAnnotatedITDsWithWrongAnnotationType() { + runTest("annotated itds with bad target"); + } + +// these tests to be completed +// public void testAnnotatedAdvice() { +// runTest("annotated advice"); +// } +// +// public void testAnnotatedAdviceWithWrongAnnotationType() { +// runTest("annotated advice with bad target"); +// } +// +// public void testAnnotatedPointcut() { +// runTest("annotated pointcut"); +// } +// +// public void testAnnotatedDeclareStatements() { +// runTest("annotated declare statements"); +// } + + public void testBasicDeclareAnnotation() { + runTest("basic declare annotation parse test"); + } + // helper methods..... public SyntheticRepository createRepos(File cpentry) { diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index 22be0285e..9c787d7b4 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -26,6 +26,19 @@ </compile> <run class="C"/> </ajc-test> + + <ajc-test dir="java5/pseudoKeywords" + title="method called around in class"> + <compile files="MethodCalledAround.java"> + </compile> + </ajc-test> + + <ajc-test dir="java5/pseudoKeywords" + title="method called around in aspect"> + <compile files="MethodCalledAroundAspect.java"> + <message kind="error" line="2"/> + </compile> + </ajc-test> <ajc-test dir="decp" pr="80249" title="Order of types passed to compiler determines weaving behavior"> <compile files="A.java,B.java,AspectX.java"/> @@ -912,7 +925,84 @@ <message kind="weave" text="Type 'SimpleVarargs' (SimpleVarargs.java:27) advised by before advice from 'VarargsAspect06' (VarargsAspect06.aj:3)"/> </compile> </ajc-test> - + + <!-- ======================================================================================= --> + <!-- annotated aspect members --> + <!-- ======================================================================================= --> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated annotations (@Target)"> + <compile files="a/Annotations.java,a/Foo.java" options="-1.5"> + <message kind="error" line="16" text="The annotation @MethodAnnotation is disallowed for this location"/> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="simple annotated aspect members"> + <compile files="a/Annotations.java,a/AnnotatedAspect.aj" options="-1.5"> + <message kind="warning" line="4" text="annotated type"/> + <message kind="warning" line="6" text="annotated field"/> + <message kind="warning" line="8" text="annotated method"/> + <message kind="warning" line="11" text="annotated constructor"/> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="simple annotated aspect members with bad target"> + <compile files="a/Annotations.java,a/AnnotatedAspect02.aj" options="-1.5"> + <message kind="error" line="3" text="The annotation @MethodAnnotation is disallowed for this location"/> + <message kind="error" line="6" text="The annotation @TypeAnnotation is disallowed for this location"/> + <message kind="error" line="8" text="The annotation @FieldAnnotation is disallowed for this location"/> + <message kind="error" line="10" text="The annotation @AnnotationAnnotation is disallowed for this location"/> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated itds"> + <compile files="a/Annotations.java,a/AnnotatedAspect03.aj" options="-1.5"> + <message kind="warning" line="4" text="annotated type"/> + <message kind="warning" line="6" text="annotated field"/> + <message kind="warning" line="8" text="annotated field"/> + <message kind="warning" line="10" text="annotated method"/> + <message kind="warning" line="12" text="annotated constructor"/> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated itds with bad target"> + <compile files="a/Annotations.java,a/AnnotatedAspect04.aj" options="-1.5"> + <message kind="error" line="6" text="The annotation @ConstructorAnnotation is disallowed for this location"/> + <message kind="error" line="8" text="The annotation @FieldAnnotation is disallowed for this location"/> + <message kind="error" line="10" text="The annotation @TypeAnnotation is disallowed for this location"/> + <!-- known limitation... + <message kind="error" line="12" text="The annotation @MethodAnnotation is disallowed for this location"/> + --> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated advice"> + <compile files="a/Annotations.java,a/AnnotatedAspect05.aj" options="-1.5"> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated advice with bad target"> + <compile files="a/Annotations.java,a/AnnotatedAspect06.aj" options="-1.5"> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated pointcut"> + <compile files="a/Annotations.java,a/AnnotatedAspect07.aj" options="-1.5"> + </compile> + </ajc-test> + + <ajc-test dir="java5/annotations/aspectMembers" title="annotated declare statements"> + <compile files="a/Annotations.java,a/AnnotatedAspect08.aj" options="-1.5"> + </compile> + </ajc-test> + + <!-- ======================================================================================= --> + <!-- declare annotation --> + <!-- ======================================================================================= --> + + <ajc-test dir="java5/annotations/declare" title="basic declare annotation parse test"> + <compile files="BasicParseTest.aj" options="-1.5"> + </compile> + </ajc-test> </suite> diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java index 0685ef0be..e02b8a214 100644 --- a/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java +++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.List; import org.aspectj.weaver.patterns.Declare; +import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.DeclareParents; import org.aspectj.weaver.patterns.DeclarePrecedence; @@ -114,6 +115,8 @@ public class CrosscuttingMembers { m.pointcut = concretePointcut; declareSofts.add(new DeclareSoft(d.getException(), concretePointcut)); addConcreteShadowMunger(m); + } else if (declare instanceof DeclareAnnotation) { + System.err.println("Need to implement CrosscuttingMembers.addDeclare for annotations"); } else { throw new RuntimeException("unimplemented"); } diff --git a/weaver/src/org/aspectj/weaver/patterns/Declare.java b/weaver/src/org/aspectj/weaver/patterns/Declare.java index c03394316..d5ffff9a1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Declare.java +++ b/weaver/src/org/aspectj/weaver/patterns/Declare.java @@ -23,6 +23,7 @@ public abstract class Declare extends PatternNode { public static final byte PARENTS = 2; public static final byte SOFT = 3; public static final byte DOMINATES = 4; + public static final byte ANNOTATION = 5; public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { byte kind = s.readByte(); @@ -35,6 +36,8 @@ public abstract class Declare extends PatternNode { return DeclareParents.read(s, context); case SOFT: return DeclareSoft.read(s, context); + case ANNOTATION: + return DeclareAnnotation.read(s,context); default: throw new RuntimeException("unimplemented"); } diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java b/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java new file mode 100644 index 000000000..003ce2a31 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java @@ -0,0 +1,143 @@ +/* ******************************************************************* + * Copyright (c) 2005 IBM Corporation + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Adrian Colyer initial implementation + * ******************************************************************/ +package org.aspectj.weaver.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.VersionedDataInputStream; + +public class DeclareAnnotation extends Declare { + + private String kind; + private TypePattern typePattern; + private SignaturePattern sigPattern; + private String annotationMethod = "unknown"; + private String annotationString = "@<annotation>"; + + public DeclareAnnotation(String kind, TypePattern typePattern) { + this.typePattern = typePattern; + this.kind = kind; + } + + public DeclareAnnotation(String kind, SignaturePattern sigPattern) { + this.sigPattern = sigPattern; + this.kind = kind; + } + + public String toString() { + StringBuffer ret = new StringBuffer(); + ret.append("declare @"); + ret.append(kind); + ret.append(" : "); + ret.append(typePattern != null ? typePattern.toString() : sigPattern.toString()); + ret.append(" : "); + ret.append(annotationString); + return ret.toString(); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Declare#resolve(org.aspectj.weaver.patterns.IScope) + */ + public void resolve(IScope scope) { + if (typePattern != null) typePattern.resolve(scope.getWorld()); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Declare#isAdviceLike() + */ + public boolean isAdviceLike() { + return false; + } + + public void setAnnotationString(String as) { + this.annotationString = as; + } + + public void setAnnotationMethod(String methName){ + this.annotationMethod = methName; + } + + + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof DeclareAnnotation)) return false; + DeclareAnnotation other = (DeclareAnnotation) obj; + if (!this.kind.equals(other.kind)) return false; + if (!this.annotationString.equals(other.annotationString)) return false; + if (!this.annotationMethod.equals(other.annotationMethod)) return false; + if (this.typePattern != null) { + if (!typePattern.equals(other.typePattern)) return false; + } + if (this.sigPattern != null) { + if (!sigPattern.equals(other.sigPattern)) return false; + } + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int result = 19; + result = 37*result + kind.hashCode(); + result = 37*result + annotationString.hashCode(); + result = 37*result + annotationMethod.hashCode(); + if (typePattern != null) result = 37*result + typePattern.hashCode(); + if (sigPattern != null) result = 37*result + sigPattern.hashCode(); + return result; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(Declare.ANNOTATION); + s.writeUTF(kind); + s.writeUTF(annotationString); + s.writeUTF(annotationMethod); + if (typePattern != null) typePattern.write(s); + if (sigPattern != null) sigPattern.write(s); + writeLocation(s); + } + + /** + * @param s + * @param context + * @return + * @throws IOException + */ + public static Declare read(VersionedDataInputStream s, + ISourceContext context) throws IOException { + DeclareAnnotation ret = null; + String kind = s.readUTF(); + String annotationString = s.readUTF(); + String annotationMethod = s.readUTF(); + TypePattern tp = null; + SignaturePattern sp = null; + if (kind.equals("type")) { + tp = TypePattern.read(s,context); + ret = new DeclareAnnotation(kind,tp); + } else { + sp = SignaturePattern.read(s,context); + ret = new DeclareAnnotation(kind,sp); + } + ret.setAnnotationString(annotationString); + ret.setAnnotationMethod(annotationMethod); + ret.readLocation(context,s); + return ret; + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index 575bcc7e1..80322fabe 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -101,7 +101,6 @@ public class PatternParser { String kind = parseIdentifier(); eat(":"); Declare ret; - //XXX beta add soft, dominates if (kind.equals("error")) { ret = parseErrorOrWarning(true); } else if (kind.equals("warning")) { @@ -122,6 +121,53 @@ public class PatternParser { ret.setLocation(sourceContext, startPos, endPos); return ret; } + + public Declare parseDeclareAnnotation() { + int startPos = tokenSource.peek().getStart(); + + eatIdentifier("declare"); + eat("@"); + String kind = parseIdentifier(); + eat(":"); + Declare ret; + if (kind.equals("type")) { + ret = parseDeclareAtType(); + } else if (kind.equals("method")) { + ret = parseDeclareAtMethod(true); + } else if (kind.equals("field")) { + ret = parseDeclareAtField(); + } else if (kind.equals("constructor")) { + ret = parseDeclareAtMethod(false); + } else { + throw new ParserException("expected one of type, method, field, constructor", + tokenSource.peek(-1)); + } + eat(";"); + int endPos = tokenSource.peek(-1).getEnd(); + ret.setLocation(sourceContext, startPos, endPos); + return ret; + + } + + public DeclareAnnotation parseDeclareAtType() { + return new DeclareAnnotation("type",parseTypePattern()); + } + + public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) { + SignaturePattern sp = parseMethodOrConstructorSignaturePattern(); + boolean isConstructorPattern = (sp.getKind() == Member.CONSTRUCTOR); + if (isMethod && isConstructorPattern) { + throw new ParserException("method signature pattern",tokenSource.peek(-1)); + } + if (!isMethod && !isConstructorPattern) { + throw new ParserException("constructor signature pattern",tokenSource.peek(-1)); + } + return new DeclareAnnotation("method",sp); // sp itself differentiates... + } + + public DeclareAnnotation parseDeclareAtField() { + return new DeclareAnnotation("field",parseFieldSignaturePattern()); + } public DeclarePrecedence parseDominates() { List l = new ArrayList(); |