aboutsummaryrefslogtreecommitdiffstats
path: root/org.aspectj.ajdt.core
diff options
context:
space:
mode:
authoracolyer <acolyer>2005-04-25 16:07:25 +0000
committeracolyer <acolyer>2005-04-25 16:07:25 +0000
commit75c1c3ea4d4cc5308cf3ba4490d18b8536b08dd2 (patch)
treed06e4c67eae3c9879eebabc6854ecf40817181d4 /org.aspectj.ajdt.core
parent92fce1440c9017376efaf544802d8cef07546b03 (diff)
downloadaspectj-75c1c3ea4d4cc5308cf3ba4490d18b8536b08dd2.tar.gz
aspectj-75c1c3ea4d4cc5308cf3ba4490d18b8536b08dd2.zip
support in ajc for parsing and error reporting of @AspectJ style aspect definitions (aspect, pointcut, advice only at this point). Also include the AddAtAspectJAnnotationsVisitor support. Switch off using -Xdev:NoAtAspectJProcessing.
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java4
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java31
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java61
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java81
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AjMethodDeclaration.java10
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java66
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java146
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java67
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java18
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java615
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java29
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java32
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java7
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java3
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java20
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java2
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java10
-rw-r--r--org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java2
-rw-r--r--org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjCompilerOptionsTest.java5
19 files changed, 1147 insertions, 62 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
index 0f8909585..af7cc30fa 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
@@ -511,7 +511,9 @@ public class BuildArgParser extends Main {
} else if (arg.equals("-XjavadocsInModel")) {
buildConfig.setGenerateModelMode(true);
buildConfig.setGenerateJavadocsInModelMode(true);
- } else if (arg.equals("-noweave") || arg.equals( "-XnoWeave")) {
+ } else if (arg.equals("-Xdev:NoAtAspectJProcessing")) {
+ buildConfig.setNoAtAspectJAnnotationProcessing(true);
+ }else if (arg.equals("-noweave") || arg.equals( "-XnoWeave")) {
buildConfig.setNoWeave(true);
} else if (arg.equals("-XserializableAspects")) {
buildConfig.setXserializableAspects(true);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java
index 9091a8c15..8085a51f4 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java
@@ -19,20 +19,24 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
+import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.core.builder.AjCompilerOptions;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.IProgressListener;
-import org.aspectj.weaver.bcel.BcelWeaver;
-import org.aspectj.weaver.bcel.BcelWorld;
-import org.aspectj.weaver.patterns.CflowPointcut;
import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
import org.aspectj.org.eclipse.jdt.internal.compiler.ICompilerAdapter;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.aspectj.weaver.bcel.BcelWeaver;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.aspectj.weaver.patterns.CflowPointcut;
/**
* @author colyer
@@ -48,6 +52,8 @@ public class AjCompilerAdapter implements ICompilerAdapter {
private boolean reportedErrors;
private boolean isXNoWeave;
private boolean proceedOnError;
+ private boolean inJava5Mode;
+ private boolean noAtAspectJAnnotationProcessing;
private IIntermediateResultsRequestor intermediateResultsRequestor;
private IProgressListener progressListener;
private IOutputClassFileNameProvider outputFileNameProvider;
@@ -55,7 +61,6 @@ public class AjCompilerAdapter implements ICompilerAdapter {
private WeaverMessageHandler weaverMessageHandler;
private Map /* fileName |-> List<UnwovenClassFile> */ binarySourceSetForFullWeave = new HashMap();
private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
-
List /*InterimResult*/ resultsPendingWeave = new ArrayList();
@@ -86,7 +91,8 @@ public class AjCompilerAdapter implements ICompilerAdapter {
Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
Collection /* InterimCompilationResult */ resultSetForFullWeave,
boolean isXNoWeave,
- boolean proceedOnError) {
+ boolean proceedOnError,
+ boolean noAtAspectJProcessing) {
this.compiler = compiler;
this.isBatchCompile = isBatchCompile;
this.weaver = weaver;
@@ -99,6 +105,10 @@ public class AjCompilerAdapter implements ICompilerAdapter {
this.binarySourceSetForFullWeave = fullBinarySourceEntries;
this.resultSetForFullWeave = resultSetForFullWeave;
this.eWorld = eFactory;
+ this.inJava5Mode = false;
+ this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
+
+ if (compiler.options.complianceLevel == CompilerOptions.JDK1_5) inJava5Mode = true;
IMessageHandler msgHandler = world.getMessageHandler();
weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
@@ -133,6 +143,17 @@ public class AjCompilerAdapter implements ICompilerAdapter {
public void beforeProcessing(CompilationUnitDeclaration unit) {
eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
+ if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
+ AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit);
+ unit.traverse(atAspectJVisitor, unit.scope);
+ }
+ }
+
+ public void beforeAnalysing(CompilationUnitDeclaration unit) {
+ if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
+ ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
+ unit.traverse(atAspectJVisitor, unit.scope);
+ }
}
public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java
new file mode 100644
index 000000000..8b4ade56e
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java
@@ -0,0 +1,61 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM Corporation Ltd
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer initial implementation
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+
+public class AddAtAspectJAnnotationsVisitor extends ASTVisitor {
+
+ private CompilationUnitDeclaration unit;
+
+ public AddAtAspectJAnnotationsVisitor(CompilationUnitDeclaration unit) {
+ this.unit = unit;
+ }
+
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ if (localTypeDeclaration instanceof AspectDeclaration) {
+ ((AspectDeclaration) localTypeDeclaration).addAtAspectJAnnotations();
+ }
+ return true;
+ }
+
+
+ public boolean visit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
+ if (memberTypeDeclaration instanceof AspectDeclaration) {
+ ((AspectDeclaration) memberTypeDeclaration).addAtAspectJAnnotations();
+ }
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+ if (typeDeclaration instanceof AspectDeclaration) {
+ ((AspectDeclaration) typeDeclaration).addAtAspectJAnnotations();
+ }
+ return true;
+ }
+ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+ if (methodDeclaration instanceof AdviceDeclaration) {
+ ((AdviceDeclaration)methodDeclaration).addAtAspectJAnnotations();
+ } else if (methodDeclaration instanceof PointcutDeclaration) {
+ ((PointcutDeclaration)methodDeclaration).addAtAspectJAnnotations();
+ }
+ return false;
+ }
+
+
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java
index a81ad0abf..6e2d95591 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java
@@ -20,14 +20,10 @@ import java.util.List;
import org.aspectj.ajdt.internal.compiler.lookup.AjTypeConstants;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.TypeX;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -37,7 +33,12 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AdviceKind;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.TypeX;
/**
* Represents before, after and around advice in an aspect.
@@ -47,22 +48,21 @@ import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
* @author Jim Hugunin
*/
public class AdviceDeclaration extends AjMethodDeclaration {
- public PointcutDesignator pointcutDesignator;
- int baseArgumentCount;
+ public PointcutDesignator pointcutDesignator; // set during parsing
+ int baseArgumentCount; // referenced by IfPseudoToken.makeArguments
- public Argument extraArgument;
+ public Argument extraArgument; // set during parsing, referenced by Proceed
- public AdviceKind kind;
+ public AdviceKind kind; // set during parsing, referenced by Proceed and AsmElementFormatter
private int extraArgumentFlags = 0;
- public MethodBinding proceedMethodBinding;
-
+ public MethodBinding proceedMethodBinding; // set during this.resolveStaments, referenced by Proceed
+ public List proceedCalls = new ArrayList(2); // populated during Proceed.findEnclosingAround
- public List proceedCalls = new ArrayList(2);
- public boolean proceedInInners;
- public ResolvedMember[] proceedCallSignatures;
- public boolean[] formalsUnchangedToProceed;
- public TypeX[] declaredExceptions;
+ private boolean proceedInInners;
+ private ResolvedMember[] proceedCallSignatures;
+ private boolean[] formalsUnchangedToProceed;
+ private TypeX[] declaredExceptions;
public AdviceDeclaration(CompilationResult result, AdviceKind kind) {
@@ -71,7 +71,7 @@ public class AdviceDeclaration extends AjMethodDeclaration {
this.kind = kind;
}
-
+ // override
protected int generateInfoAttributes(ClassFile classFile) {
List l = new ArrayList(1);
l.add(new EclipseAttributeAdapter(makeAttribute()));
@@ -80,7 +80,7 @@ public class AdviceDeclaration extends AjMethodDeclaration {
return classFile.generateMethodInfoAttribute(binding, false, l);
}
- public AjAttribute makeAttribute() {
+ private AjAttribute makeAttribute() {
if (kind == AdviceKind.Around) {
return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(),
extraArgumentFlags, sourceStart, sourceEnd, null,
@@ -92,6 +92,7 @@ public class AdviceDeclaration extends AjMethodDeclaration {
}
}
+ // override
public void resolveStatements() {
if (binding == null || ignoreFurtherInvestigation) return;
@@ -172,14 +173,14 @@ public class AdviceDeclaration extends AjMethodDeclaration {
}
}
-
+ // called by Proceed.resolveType
public int getDeclaredParameterCount() {
// this only works before code generation
return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1);
//Advice.countOnes(extraArgumentFlags);
}
- public void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
+ private void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
MethodBinding binding = (MethodBinding)proceedMethodBinding;
classFile.generateMethodInfoHeader(binding);
@@ -243,7 +244,7 @@ public class AdviceDeclaration extends AjMethodDeclaration {
}
-
+ // override
public void generateCode(ClassScope classScope, ClassFile classFile) {
if (ignoreFurtherInvestigation) return;
@@ -268,7 +269,39 @@ public class AdviceDeclaration extends AjMethodDeclaration {
return ret;
}
+ /**
+ * Add either the @Before, @After, @Around, @AfterReturning or @AfterThrowing annotation
+ */
+ public void addAtAspectJAnnotations() {
+ Annotation adviceAnnotation = null;
+ String pointcutExpression = pointcutDesignator.getPointcut().toString();
+ String extraArgumentName = "";
+ if (extraArgument != null) {
+ extraArgumentName = new String(extraArgument.name);
+ }
+
+ if (kind == AdviceKind.Before) {
+ adviceAnnotation = AtAspectJAnnotationFactory.createBeforeAnnotation(pointcutExpression,declarationSourceStart);
+ } else if (kind == AdviceKind.After) {
+ adviceAnnotation = AtAspectJAnnotationFactory.createAfterAnnotation(pointcutExpression,declarationSourceStart);
+ } else if (kind == AdviceKind.AfterReturning) {
+ adviceAnnotation = AtAspectJAnnotationFactory.createAfterReturningAnnotation(pointcutExpression,extraArgumentName,declarationSourceStart);
+ } else if (kind == AdviceKind.AfterThrowing) {
+ adviceAnnotation = AtAspectJAnnotationFactory.createAfterThrowingAnnotation(pointcutExpression,extraArgumentName,declarationSourceStart);
+ } else if (kind == AdviceKind.Around) {
+ adviceAnnotation = AtAspectJAnnotationFactory.createAroundAnnotation(pointcutExpression,declarationSourceStart);
+ }
+ if (annotations == null) {
+ annotations = new Annotation[] { adviceAnnotation };
+ } else {
+ Annotation[] old = annotations;
+ annotations = new Annotation[old.length +1];
+ System.arraycopy(old,0,annotations,0,old.length);
+ annotations[old.length] = adviceAnnotation;
+ }
+ }
+ // override, Called by ClassScope.postParse
public void postParse(TypeDeclaration typeDec) {
int adviceSequenceNumberInType = ((AspectDeclaration)typeDec).adviceCounter++;
@@ -321,7 +354,7 @@ public class AdviceDeclaration extends AjMethodDeclaration {
}
}
-
+ // called by IfPseudoToken
public static Argument[] addTjpArguments(Argument[] arguments) {
int index = arguments.length;
arguments = extendArgumentsLength(arguments, 3);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AjMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AjMethodDeclaration.java
index bb31f5e16..efaedf2b5 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AjMethodDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AjMethodDeclaration.java
@@ -25,6 +25,8 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
*/
public class AjMethodDeclaration extends MethodDeclaration {
+ private List attributes = new ArrayList();
+
/**
* @param compilationResult
*/
@@ -32,12 +34,18 @@ public class AjMethodDeclaration extends MethodDeclaration {
super(compilationResult);
}
+ // general purpose hook to add an AjAttribute to this method
+ // used by @AspectJ visitor to add pointcut attribute to @Advice
+ protected void addAttribute(EclipseAttributeAdapter eaa) {
+ attributes.add(eaa);
+ }
+
/**
* Overridden to add extra AJ stuff, also adds synthetic if boolean is true.
*/
protected int generateInfoAttributes(ClassFile classFile,boolean addAjSynthetic) {
// add extra attributes into list then call 2-arg version of generateInfoAttributes...
- List extras = new ArrayList();
+ List extras = attributes;
addDeclarationStartLineAttribute(extras,classFile);
if (addAjSynthetic) {
extras.add(new EclipseAttributeAdapter(new AjAttribute.AjSynthetic()));
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java
index 31eb13fe5..f9beb3f85 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AspectDeclaration.java
@@ -14,23 +14,53 @@
package org.aspectj.ajdt.internal.compiler.ast;
import java.lang.reflect.Modifier;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
-import org.aspectj.ajdt.internal.compiler.lookup.*;
-import org.aspectj.weaver.*;
-import org.aspectj.weaver.patterns.*;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
+import org.aspectj.ajdt.internal.compiler.lookup.HelperInterfaceBinding;
+import org.aspectj.ajdt.internal.compiler.lookup.InlineAccessFieldBinding;
+import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
-//import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-//import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Label;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IGenericType;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+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.Scope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.PerFromSuper;
+import org.aspectj.weaver.patterns.PerSingleton;
+import org.aspectj.weaver.patterns.TypePattern;
//import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -158,6 +188,28 @@ public class AspectDeclaration extends TypeDeclaration {
private FieldBinding initFailureField= null;
+ /**
+ * AMC - this method is called by the AtAspectJVisitor during beforeCompilation processing in
+ * the AjCompiler adapter. We use this hook to add in the @AspectJ annotations.
+ */
+ public void addAtAspectJAnnotations() {
+ Annotation atAspectAnnotation = AtAspectJAnnotationFactory.createAspectAnnotation(perClause.toDeclarationString(), declarationSourceStart);
+ Annotation privilegedAnnotation = null;
+ if (isPrivileged) privilegedAnnotation = AtAspectJAnnotationFactory.createPrivilegedAnnotation(declarationSourceStart);
+ Annotation[] toAdd = new Annotation[isPrivileged ? 2 : 1];
+ toAdd[0] = atAspectAnnotation;
+ if (isPrivileged) toAdd[1] = privilegedAnnotation;
+ if (annotations == null) {
+ annotations = toAdd;
+ } else {
+ Annotation[] old = annotations;
+ annotations = new Annotation[annotations.length + toAdd.length];
+ System.arraycopy(old,0,annotations,0,old.length);
+ System.arraycopy(toAdd,0,annotations,old.length,toAdd.length);
+ }
+ }
+
+
public void generateCode(ClassFile enclosingClassFile) {
if (ignoreFurtherInvestigation) {
if (binding == null)
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java
new file mode 100644
index 000000000..304cd4761
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java
@@ -0,0 +1,146 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer Initial implementation
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+
+/**
+ * @author colyer
+ * Creates @AspectJ annotations for use by AtAspectJVisitor
+ */
+public class AtAspectJAnnotationFactory {
+
+ static final char[] org = "org".toCharArray();
+ static final char[] aspectj = "aspectj".toCharArray();
+ static final char[] lang = "lang".toCharArray();
+ static final char[] internal = "internal".toCharArray();
+ static final char[] annotation = "annotation".toCharArray();
+ static final char[] value = "value".toCharArray();
+
+ static final char[] aspect = "Aspect".toCharArray();
+ static final char[] privileged = "ajcPrivileged".toCharArray();
+ static final char[] before = "Before".toCharArray();
+ static final char[] after = "After".toCharArray();
+ static final char[] afterReturning = "AfterReturning".toCharArray();
+ static final char[] afterThrowing = "AfterThrowing".toCharArray();
+ static final char[] around = "Around".toCharArray();
+ static final char[] pointcut = "Pointcut".toCharArray();
+
+ /**
+ * Create an @Aspect annotation for a code style aspect declaration starting at
+ * the given position in the source file
+ */
+ public static Annotation createAspectAnnotation(String perclause, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,aspect};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference orgAspectJLangAnnotationAspect = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation atAspectAnnotation = new NormalAnnotation(orgAspectJLangAnnotationAspect,pos);
+ if (!perclause.equals("")) {
+ // we have to set the value
+ Expression perclauseExpr = new StringLiteral(perclause.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[1];
+ mvps[0] = new MemberValuePair(value,pos,pos,perclauseExpr);
+ atAspectAnnotation.memberValuePairs = mvps;
+ }
+ return atAspectAnnotation;
+ }
+
+ public static Annotation createPrivilegedAnnotation(int pos) {
+ char[][] typeName = new char[][] {org,aspectj,internal,lang,annotation,privileged};
+ long[] positions = new long[] {pos,pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ return ann;
+ }
+
+ public static Annotation createBeforeAnnotation(String pointcutExpression, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,before};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[1];
+ mvps[0] = new MemberValuePair(value,pos,pos,pcExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+
+ public static Annotation createAfterAnnotation(String pointcutExpression, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,after};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[1];
+ mvps[0] = new MemberValuePair(value,pos,pos,pcExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+
+ public static Annotation createAfterReturningAnnotation(String pointcutExpression, String extraArgumentName, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,afterReturning};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[2];
+ mvps[0] = new MemberValuePair("pointcut".toCharArray(),pos,pos,pcExpr);
+ Expression argExpr = new StringLiteral(extraArgumentName.toCharArray(),pos,pos);
+ mvps[1] = new MemberValuePair("returning".toCharArray(),pos,pos,argExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+
+ public static Annotation createAfterThrowingAnnotation(String pointcutExpression, String extraArgumentName, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,afterThrowing};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[2];
+ mvps[0] = new MemberValuePair("pointcut".toCharArray(),pos,pos,pcExpr);
+ Expression argExpr = new StringLiteral(extraArgumentName.toCharArray(),pos,pos);
+ mvps[1] = new MemberValuePair("throwing".toCharArray(),pos,pos,argExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+
+ public static Annotation createAroundAnnotation(String pointcutExpression, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,around};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[1];
+ mvps[0] = new MemberValuePair(value,pos,pos,pcExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+
+ public static Annotation createPointcutAnnotation(String pointcutExpression, int pos) {
+ char[][] typeName = new char[][] {org,aspectj,lang,annotation,pointcut};
+ long[] positions = new long[] {pos,pos,pos,pos,pos};
+ TypeReference annType = new QualifiedTypeReference(typeName,positions);
+ NormalAnnotation ann = new NormalAnnotation(annType,pos);
+ Expression pcExpr = new StringLiteral(pointcutExpression.toCharArray(),pos,pos);
+ MemberValuePair[] mvps = new MemberValuePair[1];
+ mvps[0] = new MemberValuePair(value,pos,pos,pcExpr);
+ ann.memberValuePairs = mvps;
+ return ann;
+ }
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java
index 870a5edc0..4c46411b8 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDeclaration.java
@@ -17,20 +17,22 @@ import java.lang.reflect.Modifier;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.ResolvedPointcutDefinition;
-//import org.aspectj.weaver.ResolvedTypeX;
-//import org.aspectj.weaver.TypeX;
-import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.aspectj.org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
-import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.patterns.Pointcut;
/**
* pointcut [declaredModifiers] [declaredName]([arguments]): [pointcutDesignator];
@@ -46,6 +48,8 @@ public class PointcutDeclaration extends AjMethodDeclaration {
public PointcutDesignator pointcutDesignator;
private int declaredModifiers;
private String declaredName;
+ private boolean generateSyntheticPointcutMethod = false;
+ //private boolean mangleSelector = true;
private ResolvedPointcutDefinition resolvedPointcutDeclaration = null;
@@ -73,8 +77,14 @@ public class PointcutDeclaration extends AjMethodDeclaration {
if (arguments == null) arguments = new Argument[0];
this.declaredModifiers = modifiers;
this.declaredName = new String(selector);
- selector = CharOperation.concat(mangledPrefix, '$', selector, '$',
- Integer.toHexString(sourceStart).toCharArray());
+ // amc - if we set mangle selector to false, then the generated bytecode has the
+ // pointcut method name that the user of an @Pointcut would expect.
+ // But then we will unpack it again in the weaver which may cause redundant
+ // error messages to be issued. This seems the better trade-off...
+ //if (mangleSelector) {
+ selector = CharOperation.concat(mangledPrefix, '$', selector, '$',
+ Integer.toHexString(sourceStart).toCharArray());
+ //}
if (Modifier.isAbstract(this.declaredModifiers)) {
if (!(typeDec instanceof AspectDeclaration)) {
@@ -98,8 +108,39 @@ public class PointcutDeclaration extends AjMethodDeclaration {
}
}
+
+ /**
+ * Called from the AtAspectJVisitor to create the @Pointcut annotation
+ * (and corresponding method) for this pointcut
+ *
+ */
+ public void addAtAspectJAnnotations() {
+ Annotation pcutAnnotation = AtAspectJAnnotationFactory.createPointcutAnnotation(getPointcut().toString(),declarationSourceStart);;
+ if (annotations == null) {
+ annotations = new Annotation[] { pcutAnnotation };
+ } else {
+ Annotation[] old = annotations;
+ annotations = new Annotation[old.length +1];
+ System.arraycopy(old,0,annotations,0,old.length);
+ annotations[old.length] = pcutAnnotation;
+ }
+ generateSyntheticPointcutMethod = true;
+ }
+
+ // coming from an @Pointcut declaration
+ public void setGenerateSyntheticPointcutMethod() {
+ generateSyntheticPointcutMethod = true;
+ //mangleSelector = false;
+ }
+
public void resolve(ClassScope upperScope) {
- // this method should do nothing, use the entry point below...
+ // we attempted to resolve annotations below, but that was too early, so we do it again
+ // now at the 'right' time.
+ if (binding!= null) {
+ binding.tagBits -= TagBits.AnnotationResolved;
+ resolveAnnotations(scope, this.annotations, this.binding);
+ }
+ // for the rest of the resolution process, this method should do nothing, use the entry point below...
}
public void resolvePointcut(ClassScope upperScope) {
@@ -152,6 +193,7 @@ public class PointcutDeclaration extends AjMethodDeclaration {
public AjAttribute makeAttribute() {
return new AjAttribute.PointcutDeclarationAttribute(makeResolvedPointcutDefinition());
}
+
/**
* A pointcut declaration exists in a classfile only as an attibute on the
@@ -161,9 +203,16 @@ public class PointcutDeclaration extends AjMethodDeclaration {
public void generateCode(ClassScope classScope, ClassFile classFile) {
if (ignoreFurtherInvestigation) return ;
classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
+ if (generateSyntheticPointcutMethod) {
+ super.generateCode(classScope,classFile);
+ }
return;
}
+ protected int generateInfoAttributes(ClassFile classFile) {
+ return super.generateInfoAttributes(classFile,true);
+ }
+
public StringBuffer printReturnType(int indent, StringBuffer output) {
return output.append("pointcut");
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java
index 9bede187a..9b3b2adfa 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/PointcutDesignator.java
@@ -13,20 +13,20 @@
package org.aspectj.ajdt.internal.compiler.ast;
-import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.weaver.TypeX;
-import org.aspectj.weaver.patterns.FormalBinding;
-import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
+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.Argument;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.Pointcut;
public class PointcutDesignator extends ASTNode {
private Pointcut pointcut;
@@ -46,8 +46,14 @@ public class PointcutDesignator extends ASTNode {
pointcut = pc;
}
+ // called by AtAspectJVisitor
+ public PointcutDesignator(Pointcut pc) {
+ this.pointcut = pc;
+ }
+
public void postParse(TypeDeclaration typeDec, MethodDeclaration enclosingDec) {
- tokens.postParse(typeDec, enclosingDec);
+ if (tokens != null)
+ tokens.postParse(typeDec, enclosingDec);
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java
new file mode 100644
index 000000000..6da29969f
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java
@@ -0,0 +1,615 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM Corporation Ltd
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer initial implementation
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
+import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
+import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
+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.CompilationUnitDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.weaver.AdviceKind;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.ParserException;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+
+public class ValidateAtAspectJAnnotationsVisitor extends ASTVisitor {
+
+ private static final char[] beforeAdviceSig = "Lorg/aspectj/lang/annotation/Before;".toCharArray();
+ private static final char[] afterAdviceSig = "Lorg/aspectj/lang/annotation/After;".toCharArray();
+ private static final char[] afterReturningAdviceSig = "Lorg/aspectj/lang/annotation/AfterReturning;".toCharArray();
+ private static final char[] afterThrowingAdviceSig = "Lorg/aspectj/lang/annotation/AfterThrowing;".toCharArray();
+ private static final char[] aroundAdviceSig = "Lorg/aspectj/lang/annotation/Around;".toCharArray();
+ private static final char[] pointcutSig = "Lorg/aspectj/lang/annotation/Pointcut;".toCharArray();
+ private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
+ private static final char[] adviceNameSig = "Lorg/aspectj/lang/annotation/AdviceName;".toCharArray();
+ private static final char[] orgAspectJLangAnnotation = "org/aspectj/lang/annotation/".toCharArray();
+ private static final char[] voidType = "void".toCharArray();
+ private static final char[] joinPoint = "Lorg/aspectj/lang/JoinPoint;".toCharArray();
+ private static final char[] joinPointStaticPart = "Lorg/aspectj/lang/JoinPoint$StaticPart;".toCharArray();
+ private static final char[] joinPointEnclosingStaticPart = "Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".toCharArray();
+ private static final char[] proceedingJoinPoint = "Lorg/aspectj/lang/ProceedingJoinPoint;".toCharArray();
+ private static final char[][] adviceSigs = new char[][] {beforeAdviceSig,afterAdviceSig,afterReturningAdviceSig,afterThrowingAdviceSig,aroundAdviceSig};
+
+
+ private CompilationUnitDeclaration unit;
+ private Stack typeStack = new Stack();
+
+ public ValidateAtAspectJAnnotationsVisitor(CompilationUnitDeclaration unit) {
+ this.unit = unit;
+ }
+
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ typeStack.push(localTypeDeclaration);
+ checkTypeDeclaration(localTypeDeclaration);
+ return true;
+ }
+
+ public void endVisit(TypeDeclaration localTypeDeclaration,BlockScope scope) {
+ typeStack.pop();
+ }
+
+ public boolean visit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
+ typeStack.push(memberTypeDeclaration);
+ checkTypeDeclaration(memberTypeDeclaration);
+ return true;
+ }
+
+ public void endVisit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
+ typeStack.pop();
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+ typeStack.push(typeDeclaration);
+ checkTypeDeclaration(typeDeclaration);
+ return true;
+ }
+
+ public void endVisit(TypeDeclaration typeDeclaration,CompilationUnitScope scope) {
+ typeStack.pop();
+ }
+
+ private void checkTypeDeclaration(TypeDeclaration typeDecl) {
+ if (!(typeDecl instanceof AspectDeclaration)) {
+ if (insideAspect()) {
+ validateAspectDeclaration(typeDecl);
+ } else {
+ // check that class doesn't extend aspect
+ TypeReference parentRef = typeDecl.superclass;
+ if (parentRef != null) {
+ TypeBinding parentBinding = parentRef.resolvedType;
+ if (parentBinding instanceof SourceTypeBinding) {
+ SourceTypeBinding parentSTB = (SourceTypeBinding) parentBinding;
+ if (parentSTB.scope != null) {
+ TypeDeclaration parentDecl = parentSTB.scope.referenceContext;
+ if (isAspect(parentDecl)) {
+ typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"a class cannot extend an aspect");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // check that aspect doesn't have @Aspect annotation
+ boolean foundAspectAnnotation = false;
+ for (int i = 0; i < typeDecl.annotations.length; i++) {
+ if (typeDecl.annotations[i].resolvedType == null) continue;
+ char[] sig = typeDecl.annotations[i].resolvedType.signature();
+ if (CharOperation.equals(aspectSig,sig)) {
+ if (!foundAspectAnnotation) {
+ foundAspectAnnotation = true; // this is the one we added in the first visitor pass
+ } else {
+ //a second @Aspect annotation, user must have declared one...
+ typeDecl.scope.problemReporter().signalError(
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ "aspects cannot have @Aspect annotation"
+ );
+ }
+ }
+ }
+ }
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+ if (!methodDeclaration.getClass().equals(AjMethodDeclaration.class)) {
+ // simply test for innapropriate use of annotations on code-style members
+ if (!hasAspectJAnnotation(methodDeclaration)) return false;
+ int numPointcutAnnotations = 0;
+ int numAdviceAnnotations = 0;
+ int numAdviceNameAnnotations = 0;
+ for (int i=0; i < methodDeclaration.annotations.length; i++) {
+ if (isAspectJAnnotation(methodDeclaration.annotations[i])) {
+ if (CharOperation.equals(adviceNameSig,methodDeclaration.annotations[i].resolvedType.signature())) {
+ numAdviceNameAnnotations++;
+ } else if (CharOperation.equals(pointcutSig,methodDeclaration.annotations[i].resolvedType.signature())) {
+ numPointcutAnnotations++;
+ } else {
+ for (int j = 0; j < adviceSigs.length; j++) {
+ if (CharOperation.equals(adviceSigs[j],methodDeclaration.annotations[i].resolvedType.signature())) {
+ numAdviceAnnotations++;
+ }
+ }
+ }
+ }
+ }
+ if (methodDeclaration instanceof PointcutDeclaration) {
+ if (numPointcutAnnotations > 1 || numAdviceAnnotations > 0 || numAdviceNameAnnotations > 0) {
+ methodDeclaration.scope.problemReporter().signalError(
+ methodDeclaration.sourceStart,
+ methodDeclaration.sourceEnd,
+ "@AspectJ annotations cannot be declared on this aspect member");
+ }
+ } else if (methodDeclaration instanceof AdviceDeclaration) {
+ if (numPointcutAnnotations > 0 || numAdviceAnnotations > 1) {
+ methodDeclaration.scope.problemReporter().signalError(
+ methodDeclaration.sourceStart,
+ methodDeclaration.sourceEnd,
+ "Only @AdviceName AspectJ annotation allowed on advice");
+ }
+ } else {
+ if (numPointcutAnnotations > 0 || numAdviceAnnotations > 0 || numAdviceNameAnnotations > 0) {
+ methodDeclaration.scope.problemReporter().signalError(
+ methodDeclaration.sourceStart,
+ methodDeclaration.sourceEnd,
+ "@AspectJ annotations cannot be declared on this aspect member");
+ }
+ }
+ return false;
+ }
+ if (isAnnotationStyleAdvice(methodDeclaration.annotations)) {
+ validateAdvice(methodDeclaration);
+ } else if (isAnnotationStylePointcut(methodDeclaration.annotations)) {
+ convertToPointcutDeclaration(methodDeclaration,scope);
+ }
+ return false;
+ }
+
+
+
+ private boolean isAnnotationStyleAdvice(Annotation[] annotations) {
+ if (annotations == null) return false;
+ for (int i = 0; i < annotations.length; i++) {
+ if (annotations[i].resolvedType == null) continue;
+ char[] sig = annotations[i].resolvedType.signature();
+ if (CharOperation.equals(beforeAdviceSig,sig) ||
+ CharOperation.equals(afterAdviceSig,sig) ||
+ CharOperation.equals(afterReturningAdviceSig,sig) ||
+ CharOperation.equals(aroundAdviceSig,sig) ||
+ CharOperation.equals(afterThrowingAdviceSig,sig)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAnnotationStylePointcut(Annotation[] annotations) {
+ if (annotations == null) return false;
+ for (int i = 0; i < annotations.length; i++) {
+ if (annotations[i].resolvedType == null) continue;
+ char[] sig = annotations[i].resolvedType.signature();
+ if (CharOperation.equals(pointcutSig,sig)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasAspectJAnnotation(MethodDeclaration methodDecl) {
+ if (methodDecl.annotations == null) return false;
+ for (int i=0; i < methodDecl.annotations.length; i++) {
+ if (isAspectJAnnotation(methodDecl.annotations[i])) return true;
+ }
+ return false;
+ }
+
+ private boolean isAspectJAnnotation(Annotation ann) {
+ if (ann.resolvedType == null) return false;
+ char[] sig = ann.resolvedType.signature();
+ return CharOperation.contains(orgAspectJLangAnnotation, sig);
+ }
+
+ private boolean insideAspect() {
+ if (typeStack.empty()) return false;
+ TypeDeclaration typeDecl = (TypeDeclaration) typeStack.peek();
+ return isAspect(typeDecl);
+ }
+
+ private boolean isAspect(TypeDeclaration typeDecl) {
+ if (typeDecl instanceof AspectDeclaration) return true;
+ return hasAspectAnnotation(typeDecl);
+ }
+
+ private boolean hasAspectAnnotation(TypeDeclaration typeDecl) {
+ if (typeDecl.annotations == null) return false;
+ for (int i = 0; i < typeDecl.annotations.length; i++) {
+ if (typeDecl.annotations[i].resolvedType == null) continue;
+ char[] sig = typeDecl.annotations[i].resolvedType.signature();
+ if (CharOperation.equals(aspectSig,sig)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * nested aspect must be static
+ * cannot extend a concrete aspect
+ * pointcut in perclause must be good.
+ */
+ private void validateAspectDeclaration(TypeDeclaration typeDecl) {
+ if (typeStack.size() > 1) {
+ // it's a nested aspect
+ if (!Modifier.isStatic(typeDecl.modifiers)) {
+ typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd, "inner aspects must be static");
+ return;
+ }
+ }
+
+ SourceTypeBinding binding = typeDecl.binding;
+ if (binding != null) {
+ if (binding.isEnum() || binding.isInterface() || binding.isAnnotationType()) {
+ typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"only classes can have an @Aspect annotation");
+ }
+ }
+
+ TypeReference parentRef = typeDecl.superclass;
+ if (parentRef != null) {
+ TypeBinding parentBinding = parentRef.resolvedType;
+ if (parentBinding instanceof SourceTypeBinding) {
+ SourceTypeBinding parentSTB = (SourceTypeBinding) parentBinding;
+ TypeDeclaration parentDecl = parentSTB.scope.referenceContext;
+ if (isAspect(parentDecl) && !Modifier.isAbstract(parentDecl.modifiers)) {
+ typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"cannot extend a concrete aspect");
+ }
+ }
+ }
+
+ Annotation aspectAnnotation = null;
+ for (int i = 0; i < typeDecl.annotations.length; i++) {
+ if (typeDecl.annotations[i].resolvedType == null) continue;
+ char[] sig = typeDecl.annotations[i].resolvedType.signature();
+ if (CharOperation.equals(aspectSig,sig)) {
+ aspectAnnotation = typeDecl.annotations[i];
+ break;
+ }
+ }
+
+ int[] pcLoc = new int[2];
+ String perClause = getStringLiteralFor("value", aspectAnnotation, pcLoc);
+ AspectDeclaration aspectDecl = new AspectDeclaration(typeDecl.compilationResult);
+
+ try {
+ if (perClause != null && !perClause.equals("")) {
+ ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLoc[0]);
+ Pointcut pc = new PatternParser(perClause,context).maybeParsePerClause();
+ FormalBinding[] bindings = new FormalBinding[0];
+ if (pc != null) pc.resolve(new EclipseScope(bindings,typeDecl.scope));
+ }
+ } catch(ParserException pEx) {
+ typeDecl.scope.problemReporter().parseError(
+ pcLoc[0] + pEx.getLocation().getStart(),
+ pcLoc[0] + pEx.getLocation().getEnd() ,
+ -1,
+ perClause.toCharArray(),
+ perClause,
+ new String[] {pEx.getMessage()});
+ }
+ }
+
+ /**
+ * 1) Advice must be public
+ * 2) Advice must have a void return type if not around advice
+ * 3) Advice must not have any other @AspectJ annotations
+ */
+ private void validateAdvice(MethodDeclaration methodDeclaration) {
+
+ if (!insideAspect()) {
+ methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
+ methodDeclaration.sourceEnd,
+ "Advice must be declared inside an aspect type");
+ }
+
+ if (!Modifier.isPublic(methodDeclaration.modifiers)) {
+ methodDeclaration.scope.problemReporter()
+ .signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"advice must be public");
+ }
+
+ AdviceKind kind = null;
+ Annotation adviceAnn = null;
+ Annotation duplicateAnn = null;
+ for(int i = 0; i < methodDeclaration.annotations.length; i++) {
+ Annotation ann = methodDeclaration.annotations[i];
+ if (isAspectJAnnotation(ann)) {
+ if (adviceAnn != null) {
+ duplicateAnn = ann;
+ break;
+ }
+ if (CharOperation.equals(afterAdviceSig,ann.resolvedType.signature())) {
+ kind = AdviceKind.After;
+ adviceAnn = ann;
+ } else if (CharOperation.equals(afterReturningAdviceSig,ann.resolvedType.signature())) {
+ kind = AdviceKind.AfterReturning;
+ adviceAnn = ann;
+ } else if (CharOperation.equals(afterThrowingAdviceSig,ann.resolvedType.signature())) {
+ kind = AdviceKind.AfterThrowing;
+ adviceAnn = ann;
+ } else if (CharOperation.equals(beforeAdviceSig,ann.resolvedType.signature())) {
+ kind = AdviceKind.Before;
+ adviceAnn = ann;
+ } else if (CharOperation.equals(aroundAdviceSig,ann.resolvedType.signature())) {
+ kind = AdviceKind.Around;
+ adviceAnn = ann;
+ } else if (CharOperation.equals(adviceNameSig,ann.resolvedType.signature())) {
+ methodDeclaration.scope.problemReporter().signalError(
+ ann.sourceStart,ann.sourceEnd, "AdviceName annotation cannot be used for advice defined using annotation style");
+ }
+ }
+ }
+
+ if (duplicateAnn != null) {
+ methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(duplicateAnn);
+ }
+
+ if (kind != AdviceKind.Around) {
+ ensureVoidReturnType(methodDeclaration);
+ }
+
+ resolveAndSetPointcut(methodDeclaration, adviceAnn);
+
+ }
+
+ private void resolveAndSetPointcut(MethodDeclaration methodDeclaration, Annotation adviceAnn) {
+ int[] pcLocation = new int[2];
+ String pointcutExpression = getStringLiteralFor("pointcut",adviceAnn,pcLocation);
+ if (pointcutExpression == null) pointcutExpression = getStringLiteralFor("value",adviceAnn,pcLocation);
+ try {
+ ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLocation[0]);
+ Pointcut pc = new PatternParser(pointcutExpression,context).parsePointcut();
+ FormalBinding[] bindings = buildFormalAdviceBindingsFrom(methodDeclaration);
+ pc.resolve(new EclipseScope(bindings,methodDeclaration.scope));
+ // now create a ResolvedPointcutDefinition,make an attribute out of it, and add it to the method
+ TypeX[] paramTypes = new TypeX[bindings.length];
+ for (int i = 0; i < paramTypes.length; i++) paramTypes[i] = bindings[i].getType();
+ ResolvedPointcutDefinition resPcutDef =
+ new ResolvedPointcutDefinition(
+ EclipseFactory.fromBinding(((TypeDeclaration)typeStack.peek()).binding),
+ methodDeclaration.modifiers,
+ "anonymous",
+ paramTypes,
+ pc
+ );
+ AjAttribute attr = new AjAttribute.PointcutDeclarationAttribute(resPcutDef);
+ ((AjMethodDeclaration)methodDeclaration).addAttribute(new EclipseAttributeAdapter(attr));
+ } catch(ParserException pEx) {
+ methodDeclaration.scope.problemReporter().parseError(
+ pcLocation[0] + pEx.getLocation().getStart(),
+ pcLocation[0] + pEx.getLocation().getEnd() ,
+ -1,
+ pointcutExpression.toCharArray(),
+ pointcutExpression,
+ new String[] {pEx.getMessage()});
+ }
+ }
+
+ private void ensureVoidReturnType(MethodDeclaration methodDeclaration) {
+ boolean returnsVoid = true;
+ if ((methodDeclaration.returnType instanceof SingleTypeReference)) {
+ SingleTypeReference retType = (SingleTypeReference) methodDeclaration.returnType;
+ if (!CharOperation.equals(voidType,retType.token)) {
+ returnsVoid = false;
+ }
+ } else {
+ returnsVoid = false;
+ }
+ if (!returnsVoid) {
+ methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
+ methodDeclaration.returnType.sourceEnd,
+ "This advice must return void");
+ }
+ }
+
+ private FormalBinding[] buildFormalAdviceBindingsFrom(MethodDeclaration mDecl) {
+ if (mDecl.arguments == null) return new FormalBinding[0];
+ FormalBinding[] ret = new FormalBinding[mDecl.arguments.length];
+ for (int i = 0; i < mDecl.arguments.length; i++) {
+ Argument arg = mDecl.arguments[i];
+ String name = new String(arg.name);
+ TypeBinding argTypeBinding = mDecl.binding.parameters[i];
+ TypeX type = EclipseFactory.fromBinding(argTypeBinding);
+ if (CharOperation.equals(joinPoint,argTypeBinding.signature()) ||
+ CharOperation.equals(joinPointStaticPart,argTypeBinding.signature()) ||
+ CharOperation.equals(joinPointEnclosingStaticPart,argTypeBinding.signature()) ||
+ CharOperation.equals(proceedingJoinPoint,argTypeBinding.signature())) {
+ ret[i] = new FormalBinding.ImplicitFormalBinding(type,name,i);
+ } else {
+ ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd, "unknown");
+ }
+ }
+ return ret;
+ }
+
+ private String getStringLiteralFor(String memberName, Annotation inAnnotation, int[] location) {
+ if (inAnnotation instanceof SingleMemberAnnotation && memberName.equals("value")) {
+ SingleMemberAnnotation sma = (SingleMemberAnnotation) inAnnotation;
+ if (sma.memberValue instanceof StringLiteral) {
+ StringLiteral sv = (StringLiteral) sma.memberValue;
+ location[0] = sv.sourceStart;
+ location[1] = sv.sourceEnd;
+ return new String(sv.source());
+ }
+ }
+ if (! (inAnnotation instanceof NormalAnnotation)) return null;
+ NormalAnnotation ann = (NormalAnnotation) inAnnotation;
+ MemberValuePair[] mvps = ann.memberValuePairs;
+ if (mvps == null) return null;
+ for (int i = 0; i < mvps.length; i++) {
+ if (CharOperation.equals(memberName.toCharArray(),mvps[i].name)) {
+ if (mvps[i].value instanceof StringLiteral) {
+ StringLiteral sv = (StringLiteral) mvps[i].value;
+ location[0] = sv.sourceStart;
+ location[1] = sv.sourceEnd;
+ return new String(sv.source());
+ }
+ }
+ }
+ return null;
+ }
+
+ private void convertToPointcutDeclaration(MethodDeclaration methodDeclaration, ClassScope scope) {
+ TypeDeclaration typeDecl = (TypeDeclaration) typeStack.peek();
+ if (typeDecl.binding != null) {
+ if (!typeDecl.binding.isClass()) {
+ methodDeclaration.scope.problemReporter()
+ .signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"pointcuts can only be declared in a class or an aspect");
+ }
+ }
+
+ if (methodDeclaration.thrownExceptions != null && methodDeclaration.thrownExceptions.length > 0) {
+ methodDeclaration.scope.problemReporter()
+ .signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"pointcuts cannot throw exceptions!");
+ }
+
+ PointcutDeclaration pcDecl = new PointcutDeclaration(unit.compilationResult);
+ copyAllFields(methodDeclaration,pcDecl);
+
+ Annotation pcutAnn = null;
+ Annotation duplicateAnn = null;
+ for(int i = 0; i < methodDeclaration.annotations.length; i++) {
+ Annotation ann = methodDeclaration.annotations[i];
+ if (isAspectJAnnotation(ann)) {
+ if (pcutAnn != null) {
+ duplicateAnn = ann;
+ break;
+ }
+ if (CharOperation.equals(pointcutSig,ann.resolvedType.signature())) {
+ pcutAnn = ann;
+ }
+ }
+ }
+
+ if (duplicateAnn != null && !CharOperation.equals(pointcutSig,duplicateAnn.resolvedType.signature())) {
+ // (duplicate annotations of same type are already reported)
+ methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(duplicateAnn);
+ }
+
+ boolean returnsVoid = true;
+ if ((methodDeclaration.returnType instanceof SingleTypeReference)) {
+ SingleTypeReference retType = (SingleTypeReference) methodDeclaration.returnType;
+ if (!CharOperation.equals(voidType,retType.token)) {
+ returnsVoid = false;
+ }
+ } else {
+ returnsVoid = false;
+ }
+ if (!returnsVoid) {
+ methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
+ methodDeclaration.returnType.sourceEnd,
+ "Methods annotated with @Pointcut must return void");
+ }
+
+ if (methodDeclaration.statements != null && methodDeclaration.statements.length > 0) {
+ methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
+ methodDeclaration.returnType.sourceEnd,
+ "Pointcuts should have an empty method body");
+ }
+
+ int[] pcLocation = new int[2];
+ String pointcutExpression = getStringLiteralFor("value",pcutAnn,pcLocation);
+ try {
+ ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLocation[0]);
+ Pointcut pc = new PatternParser(pointcutExpression,context).parsePointcut();
+ pcDecl.pointcutDesignator = new PointcutDesignator(pc);
+ pcDecl.setGenerateSyntheticPointcutMethod();
+ TypeDeclaration onType = (TypeDeclaration) typeStack.peek();
+ pcDecl.postParse(onType);
+ int argsLength = methodDeclaration.arguments == null ? 0 : methodDeclaration.arguments.length;
+ FormalBinding[] bindings = new FormalBinding[argsLength];
+ for (int i = 0, len = bindings.length; i < len; i++) {
+ Argument arg = methodDeclaration.arguments[i];
+ String name = new String(arg.name);
+ TypeX type = EclipseFactory.fromBinding(methodDeclaration.binding.parameters[i]);
+ bindings[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd, "unknown");
+ }
+ swap(onType,methodDeclaration,pcDecl);
+ pc.resolve(new EclipseScope(bindings,methodDeclaration.scope));
+ } catch(ParserException pEx) {
+ methodDeclaration.scope.problemReporter().parseError(
+ pcLocation[0] + pEx.getLocation().getStart(),
+ pcLocation[0] + pEx.getLocation().getEnd() ,
+ -1,
+ pointcutExpression.toCharArray(),
+ pointcutExpression,
+ new String[] {pEx.getMessage()});
+ }
+ }
+
+ private void copyAllFields(MethodDeclaration from, MethodDeclaration to) {
+ to.annotations = from.annotations;
+ to.arguments = from.arguments;
+ to.binding = from.binding;
+ to.bits = from.bits;
+ to.bodyEnd = from.bodyEnd;
+ to.bodyStart = from.bodyStart;
+ to.declarationSourceEnd = from.declarationSourceEnd;
+ to.declarationSourceStart = from.declarationSourceStart;
+ to.errorInSignature = from.errorInSignature;
+ to.explicitDeclarations = from.explicitDeclarations;
+ to.ignoreFurtherInvestigation = from.ignoreFurtherInvestigation;
+ to.javadoc = from.javadoc;
+ to.modifiers = from.modifiers;
+ to.modifiersSourceStart = from.modifiersSourceStart;
+ to.needFreeReturn = from.needFreeReturn;
+ to.returnType = from.returnType;
+ to.scope = from.scope;
+ to.selector = from.selector;
+ to.sourceEnd = from.sourceEnd;
+ to.sourceStart = from.sourceStart;
+ to.statements = from.statements;
+ to.thrownExceptions = from.thrownExceptions;
+ to.typeParameters = from.typeParameters;
+ }
+
+ private void swap(TypeDeclaration inType, MethodDeclaration thisDeclaration, MethodDeclaration forThatDeclaration) {
+ for (int i = 0; i < inType.methods.length; i++) {
+ if (inType.methods[i] == thisDeclaration) {
+ inType.methods[i] = forThatDeclaration;
+ break;
+ }
+ }
+ }
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
index 2365ef452..197fa3376 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
@@ -29,6 +29,8 @@ import org.aspectj.bridge.WeaveMessage;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
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.QualifiedTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
@@ -307,7 +309,7 @@ public class AjLookupEnvironment extends LookupEnvironment {
// test classes don't extend aspects
if (sourceType.superclass != null) {
ResolvedTypeX parent = factory.fromEclipse(sourceType.superclass);
- if (parent.isAspect() && !(dec instanceof AspectDeclaration)) {
+ if (parent.isAspect() && !isAspect(dec)) {
factory.showMessage(IMessage.ERROR, "class \'" + new String(sourceType.sourceName) +
"\' can not extend aspect \'" + parent.getName() + "\'",
factory.fromEclipse(sourceType).getSourceLocation(), null);
@@ -319,6 +321,31 @@ public class AjLookupEnvironment extends LookupEnvironment {
buildInterTypeAndPerClause(((SourceTypeBinding) memberTypes[i]).scope);
}
}
+
+ private boolean isAspect(TypeDeclaration decl) {
+ if ((decl instanceof AspectDeclaration)) {
+ return true;
+ } else if (decl.annotations == null) {
+ return false;
+ } else {
+ for (int i = 0; i < decl.annotations.length; i++) {
+ Annotation ann = decl.annotations[i];
+ if (ann.type instanceof SingleTypeReference) {
+ if (CharOperation.equals("Aspect".toCharArray(),((SingleTypeReference)ann.type).token)) return true;
+ } else if (ann.type instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qtr = (QualifiedTypeReference) ann.type;
+ if (qtr.tokens.length != 5) return false;
+ if (!CharOperation.equals("org".toCharArray(),qtr.tokens[0])) return false;
+ if (!CharOperation.equals("aspectj".toCharArray(),qtr.tokens[1])) return false;
+ if (!CharOperation.equals("lang".toCharArray(),qtr.tokens[2])) return false;
+ if (!CharOperation.equals("annotation".toCharArray(),qtr.tokens[3])) return false;
+ if (!CharOperation.equals("Aspect".toCharArray(),qtr.tokens[4])) return false;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
private void weaveInterTypeDeclarations(CompilationUnitScope unit, Collection typeMungers,
Collection declareParents, Collection declareAnnotationOnTypes) {
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
index 90ed87495..826e585f2 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
@@ -34,6 +34,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
* @author Jim Hugunin
*/
public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
+ private static final char[] pointcutSig = "Lorg/aspectj/lang/annotation/Pointcut;".toCharArray();
protected ResolvedPointcutDefinition[] declaredPointcuts = null;
protected ResolvedMember[] declaredMethods = null;
protected ResolvedMember[] declaredFields = null;
@@ -83,6 +84,19 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
return false;
}
+ private boolean isAnnotationStylePointcut(Annotation[] annotations) {
+ if (annotations == null) return false;
+ for (int i = 0; i < annotations.length; i++) {
+ if (annotations[i].resolvedType == null) continue; // XXX happens if we do this very early from buildInterTypeandPerClause
+ // may prevent us from resolving references made in @Pointcuts to
+ // an @Pointcut in a code-style aspect
+ char[] sig = annotations[i].resolvedType.signature();
+ if (CharOperation.equals(pointcutSig,sig)) {
+ return true;
+ }
+ }
+ return false;
+ }
public WeaverStateInfo getWeaverState() {
return null;
}
@@ -113,7 +127,7 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
PointcutDeclaration d = (PointcutDeclaration)amd;
ResolvedPointcutDefinition df = d.makeResolvedPointcutDefinition();
declaredPointcuts.add(df);
- } else if (amd instanceof InterTypeDeclaration) {
+ } else if (amd instanceof InterTypeDeclaration) {
// these are handled in a separate pass
continue;
} else if (amd instanceof DeclareDeclaration &&
@@ -123,6 +137,10 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
} else if (amd instanceof AdviceDeclaration) {
// these are ignored during compilation and only used during weaving
continue;
+ } else if ((amd.annotations != null) && isAnnotationStylePointcut(amd.annotations)) {
+ // consider pointcuts defined via annotations
+ ResolvedPointcutDefinition df = makeResolvedPointcutDefinition(amd);
+ declaredPointcuts.add(df);
} else {
if (amd.binding == null || !amd.binding.isValidBinding()) continue;
declaredMethods.add(EclipseFactory.makeResolvedMember(amd.binding));
@@ -144,6 +162,18 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
declaredFields.toArray(new ResolvedMember[declaredFields.size()]);
}
+ private ResolvedPointcutDefinition makeResolvedPointcutDefinition(AbstractMethodDeclaration md) {
+ ResolvedPointcutDefinition resolvedPointcutDeclaration = new ResolvedPointcutDefinition(
+ EclipseFactory.fromBinding(md.binding.declaringClass),
+ md.modifiers,
+ new String(md.selector),
+ EclipseFactory.fromBindings(md.binding.parameters),
+ null); //??? might want to use null
+
+ resolvedPointcutDeclaration.setPosition(md.sourceStart, md.sourceEnd);
+ resolvedPointcutDeclaration.setSourceContext(new EclipseSourceContext(md.compilationResult));
+ return resolvedPointcutDeclaration;
+ }
public ResolvedMember[] getDeclaredFields() {
if (declaredFields == null) fillDeclaredMembers();
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
index 12ca5f606..cf5bcb5fb 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
@@ -508,6 +508,13 @@ public class AjBuildConfig {
options.generateModel = structureModelMode;
}
+ public boolean isNoAtAspectJAnnotationProcessing() {
+ return options.noAtAspectJProcessing;
+ }
+
+ public void setNoAtAspectJAnnotationProcessing(boolean noProcess) {
+ options.noAtAspectJProcessing = noProcess;
+ }
public void setShowWeavingInformation(boolean b) {
options.showWeavingInformation = true;
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
index c4223b8b4..1f550dd95 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
@@ -974,7 +974,8 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
state.binarySourceFiles,
state.resultsFromFile.values(),
buildConfig.isNoWeave(),
- buildConfig.getProceedOnError());
+ buildConfig.getProceedOnError(),
+ buildConfig.isNoAtAspectJAnnotationProcessing());
}
/* (non-Javadoc)
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
index 8553ed9df..0eeb1797f 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
@@ -41,8 +41,9 @@ public class AjCompilerOptions extends CompilerOptions {
public static final String OPTION_XNoInline = "org.aspectj.ajdt.core.compiler.weaver.XNoInline";
public static final String OPTION_XReweavable = "org.aspectj.ajdt.core.compiler.weaver.XReweavable";
public static final String OPTION_XReweavableCompress = "org.aspectj.ajdt.core.compiler.weaver.XReweavableCompress";
-
- // these next three not exposed by IDEs
+
+ // these next four not exposed by IDEs
+ public static final String OPTION_XDevNoAtAspectJProcessing = "org.aspectj.ajdt.core.compiler.ast.NoAtAspectJProcessing";
public static final String OPTION_GenerateModel = "org.aspectj.ajdt.core.compiler.model.GenerateModel";
public static final String OPTION_GenerateJavaDocsInModel = "org.aspectj.ajdt.core.compiler.model.GenerateJavaDocsInModel";
public static final String OPTION_Emacssym = "org.aspectj.ajdt.core.compiler.model.Emacssym";
@@ -69,10 +70,12 @@ public class AjCompilerOptions extends CompilerOptions {
// If true - autoboxing behaves differently ...
public boolean behaveInJava5Way = false;
- // these next three not exposed by IDEs
+ // these next four not exposed by IDEs
public boolean generateModel = false;
public boolean generateJavaDocsInModel = false;
public boolean generateEmacsSymFiles = false;
+ public boolean noAtAspectJProcessing = false;
+
public boolean proceedOnError = false;
@@ -119,6 +122,7 @@ public class AjCompilerOptions extends CompilerOptions {
map.put(OPTION_GenerateModel,this.generateModel ? ENABLED : DISABLED);
map.put(OPTION_GenerateJavaDocsInModel,this.generateJavaDocsInModel ? ENABLED : DISABLED);
map.put(OPTION_Emacssym,this.generateEmacsSymFiles ? ENABLED : DISABLED);
+ map.put(OPTION_XDevNoAtAspectJProcessing,this.noAtAspectJProcessing ? ENABLED : DISABLED);
return map;
}
@@ -203,6 +207,13 @@ public class AjCompilerOptions extends CompilerOptions {
this.generateEmacsSymFiles = false;
}
}
+ if ((optionValue = optionsMap.get(OPTION_XDevNoAtAspectJProcessing)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.noAtAspectJProcessing = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.noAtAspectJProcessing = false;
+ }
+ }
}
@@ -235,7 +246,8 @@ public class AjCompilerOptions extends CompilerOptions {
buf.append("\n\t- generate AJDE model: ").append(this.generateModel ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t- generate Javadocs in AJDE model: ").append(this.generateJavaDocsInModel ? ENABLED : DISABLED); //$NON-NLS-1$
- buf.append("\n\t- generate Emacs symbol files: ").append(this.generateEmacsSymFiles ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t- generate Emacs symbol files: ").append(this.generateEmacsSymFiles ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t- suppress @AspectJ processing: ").append(this.noAtAspectJProcessing ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t- invalid absolute type name (XLint): ").append(getSeverityString(InvalidAbsoluteTypeName)); //$NON-NLS-1$
buf.append("\n\t- invalid wildcard type name (XLint): ").append(getSeverityString(InvalidWildCardTypeName)); //$NON-NLS-1$
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java
index b91aed439..5407758ff 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java
@@ -139,7 +139,7 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto
return new AjCompilerAdapter(forCompiler,isBatchBuild,myBcelWorld,
myWeaver,eFactory,unwovenResultCollector,ajNotifier,fileNameProvider,bsProvider,
fullBinarySourceEntries,resultSetForFullWeave,
- ajOptions.noWeave,ajOptions.proceedOnError);
+ ajOptions.noWeave,ajOptions.proceedOnError,ajOptions.noAtAspectJProcessing);
}
/* (non-Javadoc)
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java
index d8219bee1..056120373 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseSourceContext.java
@@ -27,11 +27,21 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
public class EclipseSourceContext implements ISourceContext {
CompilationResult result;
+ int offset = 0;
public EclipseSourceContext(CompilationResult result) {
this.result = result;
}
+ public EclipseSourceContext(CompilationResult result, int offset) {
+ this.result = result;
+ this.offset = offset;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
private File getSourceFile() {
return new File(new String(result.fileName));
}
diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java
index a508e512c..0c972cf40 100644
--- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java
+++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/CommandTestCase.java
@@ -166,7 +166,7 @@ public abstract class CommandTestCase extends TestCase {
/** get the location of the org.aspectj.lang & runtime classes */
protected static String getRuntimeClasspath() {
- return "../runtime/bin" + File.pathSeparator +
+ return "../runtime/bin" + File.pathSeparator + "../aspectj5rt/bin" + File.pathSeparator +
System.getProperty("aspectjrt.path");
}
diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjCompilerOptionsTest.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjCompilerOptionsTest.java
index 988209675..c19ecc33d 100644
--- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjCompilerOptionsTest.java
+++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/core/builder/AjCompilerOptionsTest.java
@@ -45,6 +45,7 @@ public class AjCompilerOptionsTest extends TestCase {
assertFalse(options.generateModel);
assertFalse(options.generateJavaDocsInModel);
assertFalse(options.generateEmacsSymFiles);
+ assertFalse(options.noAtAspectJProcessing);
Map map = options.getMap();
assertEquals(CompilerOptions.WARNING,map.get(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName));
@@ -68,6 +69,7 @@ public class AjCompilerOptionsTest extends TestCase {
options.generateModel = true;
options.generateJavaDocsInModel = true;
options.generateEmacsSymFiles = true;
+ options.noAtAspectJProcessing = true;
Map map = options.getMap();
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_NoWeave));
@@ -79,6 +81,7 @@ public class AjCompilerOptionsTest extends TestCase {
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_GenerateModel));
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_GenerateJavaDocsInModel));
assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_Emacssym));
+ assertEquals(CompilerOptions.ENABLED,map.get(AjCompilerOptions.OPTION_XDevNoAtAspectJProcessing));
}
@@ -103,6 +106,7 @@ public class AjCompilerOptionsTest extends TestCase {
map.put(AjCompilerOptions.OPTION_GenerateModel,CompilerOptions.ENABLED);
map.put(AjCompilerOptions.OPTION_GenerateJavaDocsInModel,CompilerOptions.ENABLED);
map.put(AjCompilerOptions.OPTION_Emacssym,CompilerOptions.ENABLED);
+ map.put(AjCompilerOptions.OPTION_XDevNoAtAspectJProcessing,CompilerOptions.ENABLED);
options.set(map);
@@ -115,6 +119,7 @@ public class AjCompilerOptionsTest extends TestCase {
assertTrue(options.generateModel);
assertTrue(options.generateJavaDocsInModel);
assertTrue(options.generateEmacsSymFiles);
+ assertTrue(options.noAtAspectJProcessing);
Map newMap = options.getMap();