@@ -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; | |||
} | |||
} |
@@ -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, |
@@ -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++) { |
@@ -100,7 +100,6 @@ public class InterTypeFieldBinding extends FieldBinding { | |||
return false; | |||
} | |||
public SyntheticMethodBinding getAccessMethod(boolean isReadAccess) { | |||
if (isReadAccess) return reader; | |||
else return writer; |
@@ -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); |
@@ -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; | |||
@@ -199,6 +202,17 @@ public class DeclarationFactory implements IDeclarationFactory { | |||
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) | |||
* @see org.eclipse.jdt.internal.compiler.parser.Parser.IDeclarationFactory#createInterTypeFieldDeclaration(org.eclipse.jdt.internal.compiler.CompilationResult, org.eclipse.jdt.internal.compiler.ast.TypeReference) | |||
*/ |
@@ -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, |
@@ -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"; | |||
} |
@@ -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"; | |||
} |
@@ -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"; | |||
} |
@@ -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 {} |
@@ -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 {} |
@@ -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; | |||
} |
@@ -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 {} |
@@ -0,0 +1,3 @@ | |||
public class MethodCalledAround { | |||
void around() { ; } | |||
} |
@@ -0,0 +1,3 @@ | |||
public aspect MethodCalledAroundAspect { | |||
void around() { ; } | |||
} |
@@ -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"); | |||
} |
@@ -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) { |
@@ -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> | |||
@@ -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"); | |||
} |
@@ -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"); | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(); |