import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
-public class AdviceDeclaration extends MethodDeclaration implements IAjDeclaration {
+/**
+ * Represents before, after and around advice in an aspect.
+ * Will generate a method corresponding to the body of the advice with an
+ * attribute including additional information.
+ *
+ * @author Jim Hugunin
+ */
+public class AdviceDeclaration extends MethodDeclaration {
public PointcutDesignator pointcutDesignator;
int baseArgumentCount;
public Argument extraArgument;
- public AdviceKind kind; // adviceMunger;
+ public AdviceKind kind;
private int extraArgumentFlags = 0;
public void generateCode(ClassScope classScope, ClassFile classFile) {
- if (proceedMethodBinding != null) {
-// MethodDeclaration dec =
-// AstUtil.makeMethodDeclaration(proceedMethodBinding);
-//
-// List stmts = new ArrayList();
-//
-// Expression expr = AstUtil.makeLocalVariableReference(dec.arguments[0].binding);
-//
-//
-// stmts.add(AstUtil.makeReturnStatement(expr));
-//
-// AstUtil.setStatements(dec, stmts);
-// dec.scope = this.scope;
-// dec.generateCode(classScope, classFile);
- }
super.generateCode(classScope, classFile);
if (proceedMethodBinding != null) {
generateProceedMethod(classScope, classFile);
- public void finishParsing() {
- //kind = AdviceKind.stringToKind(new String(selector));
- //System.out.println(this + " kind " + kind + " name " + new String(selector));
- //selector = ("ajc_" + kind.toString() + "_" + Integer.toHexString(position)).toCharArray();
- //System.out.println(this + " kind " + kind + " name " + new String(selector));
-
+ public void postParse(TypeDeclaration typeDec) {
+ this.selector =
+ NameMangler.adviceName(EclipseWorld.fromBinding(typeDec.binding), kind, sourceStart).toCharArray();
if (arguments != null) {
baseArgumentCount = arguments.length;
}
arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
-
- //modifiers = checkAndSetModifiers(modifiers);
if (pointcutDesignator.isError()) {
- //System.err.println("ignoring further investigation for: " + this);
this.ignoreFurtherInvestigation = true;
}
-
-
+ pointcutDesignator.postParse(typeDec, this);
}
private int checkAndSetModifiers(int modifiers, ClassScope scope) {
s += toStringStatements(tab + 1);
return s;
}
-
- public void modifyKind(char[] name) {
- this.selector = CharArrayOps.concat(selector, name);
- }
-
-// public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) {
-// if (this.ignoreFurtherInvestigation) {
-// return false;
-// }
-//
-// if ((binding.modifiers & AccUnresolved) == 0) return true;
-//
-// //System.err.println("this " + this + ", " + binding.modifiers);
-// binding.modifiers ^= AccUnresolved;
-// //System.err.println(" post " + binding.modifiers);
-//
-//
-// return super.finishResolveTypes(sourceTypeBinding) &&
-// pointcutDesignator.finishResolveTypes(this, this.binding, baseArgumentCount, sourceTypeBinding)
-// ;
-// }
-
-
- public void postParse(TypeDeclaration typeDec) {
- this.selector =
- NameMangler.adviceName(EclipseWorld.fromBinding(typeDec.binding), kind, sourceStart).toCharArray();
- finishParsing();
- pointcutDesignator.postParse(typeDec, this);
- }
-
}
return (modifiers & AccAbstract) != 0;
}
+ public void resolve() {
+ if (binding == null || ignoreFurtherInvestigation) {
+ ignoreFurtherInvestigation = true;
+ return;
+ }
+
+ if (typeX != null) typeX.checkPointcutDeclarations();
+
+ super.resolve();
+
+ }
+
+
public void checkSpec(ClassScope scope) {
if (ignoreFurtherInvestigation) return;
if (dominatesPattern != null) {
return;
}
}
-
- //XXX need to move this somewhere that it will be applied to classes and interfaces
- // as well as to aspects, also need to handle inheritance and overriding
-// ResolvedMember[] pointcuts = myType.getDeclaredPointcuts();
-// for (int i=0, len=pointcuts.length; i < len; i++) {
-// for (int j=i+1; j < len; j++) {
-// if (pointcuts[i].getName().equals(pointcuts[j].getName())) {
-// scope.problemReporter().signalError(0, 0,
-// "duplicate pointcut name: " + pointcuts[i].getName());
-// }
-// }
-// }
}
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.parser.Parser;
-public class DeclareDeclaration extends MethodDeclaration implements IAjDeclaration {
+public class DeclareDeclaration extends MethodDeclaration {
public Declare declare;
/**
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * 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:
- * Xerox/PARC initial implementation
- * ******************************************************************/
-
-
-package org.aspectj.ajdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-
-public interface IAjDeclaration {
-// public String toString(int tab);
-// void postParse(TypeDeclaration typeDec);
-
-}
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.util.CharOperation;
-public abstract class InterTypeDeclaration extends MethodDeclaration implements IAjDeclaration {
+public abstract class InterTypeDeclaration extends MethodDeclaration {
//public AstNode myDeclaration;
public TypeReference onType;
protected ReferenceBinding onTypeBinding;
import java.io.IOException;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld;
+import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
import org.aspectj.weaver.*;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.patterns.Pointcut;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.parser.Parser;
-
-
-public class PointcutDeclaration extends MethodDeclaration implements IAjDeclaration {
+import org.eclipse.jdt.internal.compiler.util.CharOperation;
+
+/**
+ * pointcut [declaredModifiers] [declaredName]([arguments]): [pointcutDesignator];
+ *
+ * <p>No method will actually be generated for this node but an attribute
+ * will be added to the enclosing class.</p>
+ *
+ * @author Jim Hugunin
+ */
+public class PointcutDeclaration extends MethodDeclaration {
+ public static final char[] mangledPrefix = "ajc$pointcut$".toCharArray();
+
public PointcutDesignator pointcutDesignator;
+ private int declaredModifiers;
+ private String declaredName;
public PointcutDeclaration(CompilationResult compilationResult) {
super(compilationResult);
this.returnType = TypeReference.baseTypeReference(T_void, 0);
}
-// public PointcutDeclaration(MethodDeclaration decl, Parser parser) {
-// this(decl.compilationResult);
-// this.sourceEnd = decl.sourceEnd;
-// this.sourceStart = decl.sourceStart;
-//
-// this.arguments = decl.arguments;
-// if (this.arguments == null) this.arguments = new Argument[0];
-// this.modifiers = decl.modifiers;
-//// if ((modifiers & AccAbstract) == 0) {
-//// modifiers |= AccNative;
-//// }
-//// modifiers |= AccSemicolonBody; //XXX hack to make me have no body
-//
-// this.modifiersSourceStart = decl.modifiersSourceStart;
-// this.selector = decl.selector;
-// if (decl.thrownExceptions != null && decl.thrownExceptions.length > 0) {
-// //XXX need a better problem to report
-// TypeReference e1 = decl.thrownExceptions[0];
-// parser.problemReporter().parseError(e1.sourceStart, e1.sourceEnd,
-// new char[0], "throws", new String[] {":"});
-// }
-// }
-
private Pointcut getPointcut() {
if (pointcutDesignator == null) {
return Pointcut.makeMatchesNothing(Pointcut.RESOLVED);
}
}
+
+ public void parseStatements(
+ Parser parser,
+ CompilationUnitDeclaration unit) {
+ // do nothing
+ }
+
+ public void postParse(TypeDeclaration typeDec) {
+ if (arguments == null) arguments = new Argument[0];
+ this.declaredModifiers = modifiers;
+ this.declaredName = new String(selector);
+ selector = CharOperation.concat(mangledPrefix, '$', selector, '$',
+ Integer.toHexString(sourceStart).toCharArray());
+ if (pointcutDesignator == null) return; //XXX
+ pointcutDesignator.postParse(typeDec, this);
+ }
+
+ public void resolveStatements(ClassScope upperScope) {
+ if (isAbstract()) this.modifiers |= AccSemicolonBody;
+
+ if (binding == null || ignoreFurtherInvestigation) return;
+
+ if (pointcutDesignator != null) {
+ pointcutDesignator.finishResolveTypes(this, this.binding, arguments.length,
+ upperScope.referenceContext.binding);
+ }
+
+ super.resolveStatements(upperScope);
+ }
+
public ResolvedPointcutDefinition makeResolvedPointcutDefinition() {
//System.out.println("pc: " + getPointcut());
- return new ResolvedPointcutDefinition(
+ ResolvedPointcutDefinition ret = new ResolvedPointcutDefinition(
EclipseWorld.fromBinding(this.binding.declaringClass),
- this.modifiers, // & ~AccNative,
- new String(selector),
+ declaredModifiers,
+ declaredName,
EclipseWorld.fromBindings(this.binding.parameters),
getPointcut());
+
+ ret.setPosition(sourceStart, sourceEnd);
+ ret.setSourceContext(new EclipseSourceContext(compilationResult));
+ return ret;
}
public AjAttribute makeAttribute() {
return new AjAttribute.PointcutDeclarationAttribute(makeResolvedPointcutDefinition());
-// return new Attribute() {
-// public char[] getAttributeName() { return ResolvedPointcutDefinition.AttributeName.toCharArray(); }
-// public void writeTo(DataOutputStream s) throws IOException {
-// makeResolvedPointcut().writeAttribute(s);
-// }
-// };
}
/**
return;
}
-
-
-// public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) {
-// if (!super.finishResolveTypes(sourceTypeBinding)) return false;
-// if (pointcutDesignator != null) {
-// return pointcutDesignator.finishResolveTypes(this, this.binding, arguments.length, sourceTypeBinding);
-// } else {
-// return true;
-// }
-// }
-
public String toString(int tab) {
StringBuffer buf = new StringBuffer();
buf.append(tabString(tab));
if (modifiers != 0) {
buf.append(modifiersString(modifiers));
}
-
-// if (modifiers != AccNative) {
-// buf.append(modifiersString(modifiers & ~AccNative));
-// }
-
+
buf.append("pointcut ");
buf.append(new String(selector));
buf.append("(");
buf.append(";");
return buf.toString();
}
-
- public void parseStatements(
- Parser parser,
- CompilationUnitDeclaration unit) {
- if (pointcutDesignator == null) {
- //XXXthrow new RuntimeException("unimplemented");
- } else {
- // do nothing
- }
- }
-
- public void postParse(TypeDeclaration typeDec) {
- if (arguments == null) arguments = new Argument[0];
- if (pointcutDesignator == null) return; //XXX
- pointcutDesignator.postParse(typeDec, this);
- }
-
- public void resolveStatements(ClassScope upperScope) {
- if (isAbstract()) this.modifiers |= AccSemicolonBody;
-
- if (binding == null || ignoreFurtherInvestigation) return;
-
- if (pointcutDesignator != null) {
- pointcutDesignator.finishResolveTypes(this, this.binding, arguments.length,
- upperScope.referenceContext.binding);
- }
-
-
- super.resolveStatements(upperScope);
- }
-
}
import org.aspectj.ajdt.internal.compiler.ast.*;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
+import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.*;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.*;
if (amd == null) continue; //???
if (amd instanceof PointcutDeclaration) {
PointcutDeclaration d = (PointcutDeclaration)amd;
- declaredPointcuts.add(d.makeResolvedPointcutDefinition());
+ ResolvedPointcutDefinition df = d.makeResolvedPointcutDefinition();
+ declaredPointcuts.add(df);
} else {
//XXX this doesn't handle advice quite right
declaredMethods.add(eclipseWorld().makeResolvedMember(m));
return crosscuttingMembers;
}
+
+ //XXX make sure this is applied to classes and interfaces
+ public void checkPointcutDeclarations() {
+ ResolvedMember[] pointcuts = getDeclaredPointcuts();
+ for (int i=0, len=pointcuts.length; i < len; i++) {
+ if (pointcuts[i].isAbstract()) {
+ if (!this.isAspect()) {
+ MessageUtil.error(
+ "abstract pointcut only allowed in aspect" + pointcuts[i].getName(),
+ pointcuts[i].getSourceLocation());
+ } else if (!this.isAbstract()) {
+ MessageUtil.error(
+ "abstract pointcut in concrete aspect" + pointcuts[i].getName(),
+ pointcuts[i].getSourceLocation());
+ }
+ }
+
+ for (int j=i+1; j < len; j++) {
+ if (pointcuts[i].getName().equals(pointcuts[j].getName())) {
+ eclipseWorld().getMessageHandler().handleMessage(
+ MessageUtil.error(
+ "duplicate pointcut name: " + pointcuts[j].getName(),
+ pointcuts[j].getSourceLocation()));
+ }
+ }
+ }
+
+ //XXX now check all inherited pointcuts to be sure that they're handled reasonably
+
+
+
+
+ }
+
}
import java.util.*;
+import org.aspectj.bridge.*;
import org.aspectj.weaver.*;
import org.aspectj.weaver.patterns.*;
-import org.aspectj.bridge.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.util.CharOperation;
+/**
+ * Adaptor from org.eclipse.jdt.internal.compiler.lookup.Scope to org.aspectj.weaver.IScope
+ *
+ * @author Jim Hugunin
+ */
public class EclipseScope implements IScope {
private Scope scope;
private EclipseWorld world;
import java.lang.reflect.Modifier;
import java.util.Iterator;
+import org.aspectj.ajdt.internal.compiler.ast.*;
import org.aspectj.ajdt.internal.compiler.ast.Proceed;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld;
import org.aspectj.util.FuzzyBoolean;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.CharOperation;
+/**
+ * Extends problem reporter to support compiler-side implementation of declare soft.
+ * Also overrides error reporting for the need to implement abstract methods to
+ * account for inter-type declarations and pointcut declarations. This second
+ * job might be better done directly in the SourceTypeBinding/ClassScope classes.
+ *
+ * @author Jim Hugunin
+ */
public class AjProblemReporter extends ProblemReporter {
private static final boolean DUMP_STACK = false;
super.unhandledException(exceptionType, location);
}
- public void handle(
- int problemId,
- String[] problemArguments,
- int severity,
- int problemStartPosition,
- int problemEndPosition,
- ReferenceContext referenceContext,
- CompilationResult unitResult) {
-
- if (severity != Ignore && DUMP_STACK) {
- Thread.currentThread().dumpStack();
+ private boolean isPointcutDeclaration(MethodBinding binding) {
+ return CharOperation.startsWith(binding.selector, PointcutDeclaration.mangledPrefix);
+ }
+
+ public void abstractMethodCannotBeOverridden(
+ SourceTypeBinding type,
+ MethodBinding concreteMethod)
+ {
+ if (isPointcutDeclaration(concreteMethod)) {
+ return;
}
- super.handle(
- problemId,
- problemArguments,
- severity,
- problemStartPosition,
- problemEndPosition,
- referenceContext,
- unitResult);
+ super.abstractMethodCannotBeOverridden(type, concreteMethod);
}
+
public void abstractMethodMustBeImplemented(
SourceTypeBinding type,
MethodBinding abstractMethod)
{
+ // if this is a PointcutDeclaration then there is no error
+ if (isPointcutDeclaration(abstractMethod)) {
+ return;
+ }
+
+
// if we implemented this method by an inter-type declaration, then there is no error
//??? be sure this is always right
ResolvedTypeX onTypeX = world.fromEclipse(type); //abstractMethod.declaringClass);
super.abstractMethodMustBeImplemented(type, abstractMethod);
}
+ public void handle(
+ int problemId,
+ String[] problemArguments,
+ int severity,
+ int problemStartPosition,
+ int problemEndPosition,
+ ReferenceContext referenceContext,
+ CompilationResult unitResult) {
+
+ if (severity != Ignore && DUMP_STACK) {
+ Thread.currentThread().dumpStack();
+ }
+ super.handle(
+ problemId,
+ problemArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ referenceContext,
+ unitResult);
+ }
+
+
+
}
package org.aspectj.weaver;
import java.io.*;
+import java.lang.reflect.Modifier;
import org.aspectj.bridge.ISourceLocation;
this.end = sourceEnd;
}
+ public void setSourceContext(ISourceContext sourceContext) {
+ this.sourceContext = sourceContext;
+ }
+
+ public boolean isAbstract() {
+ return Modifier.isAbstract(modifiers);
+ }
+
}
public final int hashCode() {
return signature.hashCode();
}
+
+ public static TypeX makeArray(TypeX base, int dims) {
+ StringBuffer sig = new StringBuffer();
+ for (int i=0; i < dims; i++) sig.append("[");
+ sig.append(base.getSignature());
+ return TypeX.forSignature(sig.toString());
+ }
/**
* Constructs a TypeX for a java language type name. For example:
import java.io.*;
+import org.aspectj.bridge.IMessage;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.*;
import org.aspectj.weaver.ast.*;
public void resolveBindings(IScope scope, Bindings bindings) {
arguments.resolveBindings(scope, bindings, true);
+ if (arguments.ellipsisCount > 1) {
+ scope.message(IMessage.ERROR, this,
+ "uses more than one .. in args (compiler limitation)");
+ }
}
public void postRead(ResolvedTypeX enclosingType) {
scope.getWorld().getLint().invalidAbsoluteTypeName.signal(cleanName, getSourceLocation());
}
} else {
+ if (dim != 0) type = TypeX.makeArray(type, dim);
TypePattern ret = new ExactTypePattern(type, includeSubtypes);
ret.copyLocationFrom(this);
return ret;