| /* ******************************************************************* |
| * 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); |
| } |
| } |