/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} |
/** | /** | ||||
* 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 | * class. Unlike advice and inter-type declarations, it has no corresponding | ||||
* method. | * 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) { | public void generateCode(ClassScope classScope, ClassFile classFile) { | ||||
classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.DeclareAttribute(declareDecl))); | classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.DeclareAttribute(declareDecl))); | ||||
if (shouldDelegateCodeGeneration()) { | |||||
super.generateCode(classScope,classFile); | |||||
} | |||||
return; | return; | ||||
} | } | ||||
protected boolean shouldDelegateCodeGeneration() { | |||||
return false; | |||||
} | |||||
public void parseStatements( | public void parseStatements( | ||||
Parser parser, | Parser parser, |
} | } | ||||
} | } | ||||
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) { | public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) { | ||||
for (int i=0, len=tokens.length; i < len; i++) { | for (int i=0, len=tokens.length; i < len; i++) { |
return false; | return false; | ||||
} | } | ||||
public SyntheticMethodBinding getAccessMethod(boolean isReadAccess) { | public SyntheticMethodBinding getAccessMethod(boolean isReadAccess) { | ||||
if (isReadAccess) return reader; | if (isReadAccess) return reader; | ||||
else return writer; | else return writer; |
} | } | ||||
//XXX this is identical to InterTypeFieldBinding | //XXX this is identical to InterTypeFieldBinding | ||||
public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { | public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) { | ||||
scope.compilationUnitScope().recordTypeReference(declaringClass); | scope.compilationUnitScope().recordTypeReference(declaringClass); |
import org.aspectj.ajdt.internal.compiler.ast.AjConstructorDeclaration; | import org.aspectj.ajdt.internal.compiler.ast.AjConstructorDeclaration; | ||||
import org.aspectj.ajdt.internal.compiler.ast.AjMethodDeclaration; | import org.aspectj.ajdt.internal.compiler.ast.AjMethodDeclaration; | ||||
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration; | 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.DeclareDeclaration; | ||||
import org.aspectj.ajdt.internal.compiler.ast.IfPseudoToken; | import org.aspectj.ajdt.internal.compiler.ast.IfPseudoToken; | ||||
import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration; | import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration; | ||||
import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; | import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; | ||||
import org.aspectj.weaver.AdviceKind; | import org.aspectj.weaver.AdviceKind; | ||||
import org.aspectj.weaver.patterns.Declare; | 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.CompilationResult; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode; | 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.Argument; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; | import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; | import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; | ||||
return new DeclareDeclaration(result,declare); | return new DeclareDeclaration(result,declare); | ||||
} | } | ||||
/* (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) | /* (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) | * @see org.eclipse.jdt.internal.compiler.parser.Parser.IDeclarationFactory#createInterTypeFieldDeclaration(org.eclipse.jdt.internal.compiler.CompilationResult, org.eclipse.jdt.internal.compiler.ast.TypeReference) | ||||
*/ | */ |
import org.aspectj.org.eclipse.jdt.internal.compiler.IProblemFactory; | 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.ASTNode; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; | 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.ast.ExplicitConstructorCall; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; | 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.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.MethodBinding; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; | 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.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.lookup.TypeBinding; | ||||
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter; | import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter; | ||||
import org.aspectj.util.FuzzyBoolean; | import org.aspectj.util.FuzzyBoolean; | ||||
super.abstractMethodMustBeImplemented(type, abstractMethod); | 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( | public void handle( | ||||
int problemId, | int problemId, | ||||
String[] problemArguments, | String[] problemArguments, |
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"; | |||||
} |
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"; | |||||
} |
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"; | |||||
} |
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 {} |
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 {} |
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; | |||||
} |
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 {} |
public class MethodCalledAround { | |||||
void around() { ; } | |||||
} |
public aspect MethodCalledAroundAspect { | |||||
void around() { ; } | |||||
} |
} | } | ||||
} | } | ||||
public void test_aroundMethod() { | |||||
runTest("method called around in class"); | |||||
} | |||||
public void test_aroundMethodAspect() { | |||||
runTest("method called around in aspect"); | |||||
} | |||||
public void test_ambiguousBindingsDetection() { | public void test_ambiguousBindingsDetection() { | ||||
runTest("Various kinds of ambiguous bindings"); | runTest("Various kinds of ambiguous bindings"); | ||||
} | } |
} | } | ||||
} | } | ||||
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..... | // helper methods..... | ||||
public SyntheticRepository createRepos(File cpentry) { | public SyntheticRepository createRepos(File cpentry) { |
</compile> | </compile> | ||||
<run class="C"/> | <run class="C"/> | ||||
</ajc-test> | </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"> | <ajc-test dir="decp" pr="80249" title="Order of types passed to compiler determines weaving behavior"> | ||||
<compile files="A.java,B.java,AspectX.java"/> | <compile files="A.java,B.java,AspectX.java"/> | ||||
<message kind="weave" text="Type 'SimpleVarargs' (SimpleVarargs.java:27) advised by before advice from 'VarargsAspect06' (VarargsAspect06.aj:3)"/> | <message kind="weave" text="Type 'SimpleVarargs' (SimpleVarargs.java:27) advised by before advice from 'VarargsAspect06' (VarargsAspect06.aj:3)"/> | ||||
</compile> | </compile> | ||||
</ajc-test> | </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> | </suite> | ||||
import java.util.List; | import java.util.List; | ||||
import org.aspectj.weaver.patterns.Declare; | import org.aspectj.weaver.patterns.Declare; | ||||
import org.aspectj.weaver.patterns.DeclareAnnotation; | |||||
import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | ||||
import org.aspectj.weaver.patterns.DeclareParents; | import org.aspectj.weaver.patterns.DeclareParents; | ||||
import org.aspectj.weaver.patterns.DeclarePrecedence; | import org.aspectj.weaver.patterns.DeclarePrecedence; | ||||
m.pointcut = concretePointcut; | m.pointcut = concretePointcut; | ||||
declareSofts.add(new DeclareSoft(d.getException(), concretePointcut)); | declareSofts.add(new DeclareSoft(d.getException(), concretePointcut)); | ||||
addConcreteShadowMunger(m); | addConcreteShadowMunger(m); | ||||
} else if (declare instanceof DeclareAnnotation) { | |||||
System.err.println("Need to implement CrosscuttingMembers.addDeclare for annotations"); | |||||
} else { | } else { | ||||
throw new RuntimeException("unimplemented"); | throw new RuntimeException("unimplemented"); | ||||
} | } |
public static final byte PARENTS = 2; | public static final byte PARENTS = 2; | ||||
public static final byte SOFT = 3; | public static final byte SOFT = 3; | ||||
public static final byte DOMINATES = 4; | public static final byte DOMINATES = 4; | ||||
public static final byte ANNOTATION = 5; | |||||
public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { | public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { | ||||
byte kind = s.readByte(); | byte kind = s.readByte(); | ||||
return DeclareParents.read(s, context); | return DeclareParents.read(s, context); | ||||
case SOFT: | case SOFT: | ||||
return DeclareSoft.read(s, context); | return DeclareSoft.read(s, context); | ||||
case ANNOTATION: | |||||
return DeclareAnnotation.read(s,context); | |||||
default: | default: | ||||
throw new RuntimeException("unimplemented"); | throw new RuntimeException("unimplemented"); | ||||
} | } |
/* ******************************************************************* | |||||
* 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; | |||||
} | |||||
} |
String kind = parseIdentifier(); | String kind = parseIdentifier(); | ||||
eat(":"); | eat(":"); | ||||
Declare ret; | Declare ret; | ||||
//XXX beta add soft, dominates | |||||
if (kind.equals("error")) { | if (kind.equals("error")) { | ||||
ret = parseErrorOrWarning(true); | ret = parseErrorOrWarning(true); | ||||
} else if (kind.equals("warning")) { | } else if (kind.equals("warning")) { | ||||
ret.setLocation(sourceContext, startPos, endPos); | ret.setLocation(sourceContext, startPos, endPos); | ||||
return ret; | 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() { | public DeclarePrecedence parseDominates() { | ||||
List l = new ArrayList(); | List l = new ArrayList(); |