blob: 23b61b393c8a8b232ed48c9cb591d1b35069fb77 [file] [log] [blame]
/* *******************************************************************
* 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;
import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
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.problem.AbortCompilation;
import java.util.Stack;
/**
* This aspect implements the necessary hooks around the JDT compiler to allow AspectJ to do its
* job
*/
public privileged aspect CompilerAdapter {
/**
* A default adapter factory for circumstances when this code is used outside of AspectJ
* Seems overkill?? Will that ever happen???
*/
private static ICompilerAdapterFactory adapterFactory =
new ICompilerAdapterFactory() {
@Override
public ICompilerAdapter getAdapter(Compiler forCompiler) {
return new DefaultCompilerAdapter(forCompiler);
}
};
/**
* Called by AspectJ to inform the JDT of the AspectJ compiler adapter factor to use.
*/
public static void setCompilerAdapterFactory(ICompilerAdapterFactory factory) {
adapterFactory = factory;
}
/**
* If annotation processing is enabled method Compiler.compile(..) could be called recursively.
* So here we introduce stack of adapters instead of single adapter to drive on compilation events.
*/
private final Stack<ICompilerAdapter> compilerAdapterStack = new Stack<ICompilerAdapter>();
pointcut dietParsing(Compiler compiler):
execution(void Compiler.beginToCompile(ICompilationUnit[])) && this(compiler);
pointcut compiling(Compiler compiler, ICompilationUnit[] sourceUnits) :
execution(* Compiler.compile(..)) && args(sourceUnits) && this(compiler);
pointcut processing(CompilationUnitDeclaration unit, int index) :
execution(* Compiler.process(..)) && args(unit,index);
pointcut resolving(CompilationUnitDeclaration unit) :
call(* CompilationUnitDeclaration.resolve(..)) && target(unit) && within(Compiler);
pointcut analysing(CompilationUnitDeclaration unit) :
call(* CompilationUnitDeclaration.analyseCode(..)) && target(unit) && within(Compiler);
pointcut generating(CompilationUnitDeclaration unit) :
call(* CompilationUnitDeclaration.generateCode(..)) && target(unit) && within(Compiler);
before(Compiler compiler, ICompilationUnit[] sourceUnits) : compiling(compiler, sourceUnits) {
final ICompilerAdapter compilerAdapter = adapterFactory.getAdapter(compiler);
compilerAdapterStack.push(compilerAdapter);
compilerAdapter.beforeCompiling(sourceUnits);
}
after(Compiler compiler) returning : compiling(compiler, ICompilationUnit[]) {
try {
final ICompilerAdapter compilerAdapter = compilerAdapterStack.pop();
compilerAdapter.afterCompiling(compiler.unitsToProcess);
} catch (AbortCompilation e) {
compiler.handleInternalException(e, null);
} catch (Error e) {
compiler.handleInternalException(e, null, null);
throw e; // rethrow
} catch (RuntimeException e) {
compiler.handleInternalException(e, null, null);
throw e; // rethrow
} finally {
if (compilerAdapterStack.isEmpty())
compiler.reset();
}
}
before(CompilationUnitDeclaration unit, int index) : processing(unit,index) {
compilerAdapterStack.peek().beforeProcessing(unit);
}
after(Compiler compiler) returning(): dietParsing(compiler){
compilerAdapterStack.peek().afterDietParsing(compiler.unitsToProcess);
}
// We want this to run even in the erroneous case to ensure 'compiled:' gets out...
after(CompilationUnitDeclaration unit, int index) : processing(unit, index) {
compilerAdapterStack.peek().afterProcessing(unit,index);
}
before(CompilationUnitDeclaration unit) : resolving(unit) {
compilerAdapterStack.peek().beforeResolving(unit);
}
after(CompilationUnitDeclaration unit) returning : resolving(unit) {
compilerAdapterStack.peek().afterResolving(unit);
}
before(CompilationUnitDeclaration unit) : analysing(unit) {
compilerAdapterStack.peek().beforeAnalysing(unit);
}
after(CompilationUnitDeclaration unit) returning : analysing(unit) {
compilerAdapterStack.peek().afterAnalysing(unit);
}
before(CompilationUnitDeclaration unit) : generating(unit) {
compilerAdapterStack.peek().beforeGenerating(unit);
}
after(CompilationUnitDeclaration unit) returning : generating(unit) {
compilerAdapterStack.peek().afterGenerating(unit);
}
}