Package org.aspectj.ajdt.internal.compiler

Source Code of org.aspectj.ajdt.internal.compiler.AjCompilerAdapter

/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.aspectj.ajdt.internal.compiler;

import java.io.IOException;
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.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.AjState;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.IProgressListener;
import org.aspectj.bridge.context.CompilationAndWeavingContext;
import org.aspectj.bridge.context.ContextToken;
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.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.aspectj.weaver.bcel.BcelWeaver;
import org.aspectj.weaver.bcel.BcelWorld;

/**
* @author colyer
*
*         Adapts standard JDT Compiler to add in AspectJ specific behaviours.
*/
public class AjCompilerAdapter extends AbstractCompilerAdapter {

  private Compiler compiler;
  private BcelWeaver weaver;
  private EclipseFactory eWorld;
  private boolean isBatchCompile;
  private boolean reportedErrors;
  private boolean isXTerminateAfterCompilation;
  private boolean proceedOnError;
  private boolean inJava5Mode;
  private boolean reflectable;
  private boolean noAtAspectJAnnotationProcessing;
  private IIntermediateResultsRequestor intermediateResultsRequestor;
  private IProgressListener progressListener;
  private IOutputClassFileNameProvider outputFileNameProvider;
  private IBinarySourceProvider binarySourceProvider;
  private WeaverMessageHandler weaverMessageHandler;
  private Map /* fileName |-> List<UnwovenClassFile> */binarySourceSetForFullWeave = new HashMap();

  private ContextToken processingToken = null;
  private ContextToken resolvingToken = null;
  private ContextToken analysingToken = null;
  private ContextToken generatingToken = null;

  private AjState incrementalCompilationState;

  List /* InterimResult */resultsPendingWeave = new ArrayList();

  /**
   * Create an adapter, and tell it everything it needs to now to drive the AspectJ parts of a compile cycle.
   *
   * @param compiler the JDT compiler that produces class files from source
   * @param isBatchCompile true if this is a full build (non-incremental)
   * @param world the bcelWorld used for type resolution during weaving
   * @param weaver the weaver
   * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
   * @param outputFileNameProvider implementor of a strategy providing output file names for results
   * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
   * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines that we need to weave the world,
   *        this is the set of intermediate results that will be passed to the weaver.
   */
  public AjCompilerAdapter(Compiler compiler, boolean isBatchCompile, BcelWorld world, BcelWeaver weaver,
      EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, IProgressListener progressListener,
      IOutputClassFileNameProvider outputFileNameProvider, IBinarySourceProvider binarySourceProvider,
      Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
      boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing, boolean reflectable,
      AjState incrementalCompilationState) {
    this.compiler = compiler;
    this.isBatchCompile = isBatchCompile;
    this.weaver = weaver;
    this.intermediateResultsRequestor = intRequestor;
    this.progressListener = progressListener;
    this.outputFileNameProvider = outputFileNameProvider;
    this.binarySourceProvider = binarySourceProvider;
    this.isXTerminateAfterCompilation = isXterminateAfterCompilation;
    this.proceedOnError = proceedOnError;
    this.binarySourceSetForFullWeave = fullBinarySourceEntries;
    this.eWorld = eFactory;
    this.reflectable = reflectable;
    this.inJava5Mode = false;
    this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
    this.incrementalCompilationState = incrementalCompilationState;

    if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) {
      inJava5Mode = true;
    }

    IMessageHandler msgHandler = world.getMessageHandler();
    // Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
    if (msgHandler instanceof WeaverMessageHandler) {
      ((WeaverMessageHandler) msgHandler).resetCompiler(compiler);
      weaverMessageHandler = (WeaverMessageHandler) msgHandler;
    } else {
      weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
      world.setMessageHandler(weaverMessageHandler);
    }
  }

  // the compilation lifecycle methods below are called in order as compilation progresses...

  public void beforeCompiling(ICompilationUnit[] sourceUnits) {
    resultsPendingWeave = new ArrayList();
    reportedErrors = false;
  }

  public void beforeProcessing(CompilationUnitDeclaration unit) {
    eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
    processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT, unit
        .getFileName());
    if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
      ContextToken tok = CompilationAndWeavingContext.enteringPhase(
          CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
      AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, reflectable);
      unit.traverse(atAspectJVisitor, unit.scope);
      CompilationAndWeavingContext.leavingPhase(tok);
    }
  }

  public void beforeResolving(CompilationUnitDeclaration unit) {
    resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit
        .getFileName());
  }

  public void afterResolving(CompilationUnitDeclaration unit) {
    if (resolvingToken != null) {
      CompilationAndWeavingContext.leavingPhase(resolvingToken);
    }
  }

  public void beforeAnalysing(CompilationUnitDeclaration unit) {
    analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit
        .getFileName());
    if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
      ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
      unit.traverse(atAspectJVisitor, unit.scope);
    }
  }

  public void afterAnalysing(CompilationUnitDeclaration unit) {
    if (analysingToken != null) {
      CompilationAndWeavingContext.leavingPhase(analysingToken);
    }
  }

  public void beforeGenerating(CompilationUnitDeclaration unit) {
    generatingToken = CompilationAndWeavingContext.enteringPhase(
        CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
  }

  public void afterGenerating(CompilationUnitDeclaration unit) {
    if (generatingToken != null) {
      CompilationAndWeavingContext.leavingPhase(generatingToken);
    }
  }

  public void afterCompiling(CompilationUnitDeclaration[] units) {
    this.eWorld.cleanup();
    try {
      // not great ... but one more check before we continue, see pr132314
      if (!reportedErrors && units != null) {
        for (int i = 0; i < units.length; i++) {
          if (units[i] != null && units[i].compilationResult != null && units[i].compilationResult.hasErrors()) {
            reportedErrors = true;
            break;
          }
        }
      }
      if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
        // no point weaving... just tell the requestor we're done
        notifyRequestor();
      } else {
        weave(); // notification happens as weave progresses...
        // weaver.getWorld().flush(); // pr152257
      }
    } catch (IOException ex) {
      AbortCompilation ac = new AbortCompilation(null, ex);
      throw ac;
    } catch (RuntimeException rEx) {
      if (rEx instanceof AbortCompilation) {
        throw rEx; // Don't wrap AbortCompilation exceptions!
      }

      // This will be unwrapped in Compiler.handleInternalException() and the nested
      // RuntimeException thrown back to the original caller - which is AspectJ
      // which will then then log it as a compiler problem.
      throw new AbortCompilation(true, rEx);
    }
  }

  public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
    CompilationAndWeavingContext.leavingPhase(processingToken);
    eWorld.finishedCompilationUnit(unit);
    InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult, outputFileNameProvider);
    if (unit.compilationResult.hasErrors()) {
      reportedErrors = true;
    }

    if (intermediateResultsRequestor != null) {
      intermediateResultsRequestor.acceptResult(intRes);
    }

    if (isXTerminateAfterCompilation) {
      acceptResult(unit.compilationResult);
    } else {
      resultsPendingWeave.add(intRes);
    }
  }

  // public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean
  // analyzeCode, boolean generateCode) {
  // resultsPendingWeave = new ArrayList();
  // reportedErrors = false;
  // }
  //
  // public void afterResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean
  // analyzeCode, boolean generateCode) {
  // InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
  // if (unit.compilationResult.hasErrors()) reportedErrors = true;
  // if (isXNoWeave || !generateCode) {
  // acceptResult(unit.compilationResult);
  // } else if (generateCode){
  // resultsPendingWeave.add(intRes);
  // try {
  // weave();
  // } catch (IOException ex) {
  // AbortCompilation ac = new AbortCompilation(null,ex);
  // throw ac;
  // }
  // }
  // }

  // helper methods...
  // ==================================================================================

  /*
   * Called from the weaverAdapter once it has finished weaving the class files associated with a given compilation result.
   */
  public void acceptResult(CompilationResult result) {
    compiler.requestor.acceptResult(result.tagAsAccepted());
    if (compiler.unitsToProcess != null) {
      for (int i = 0; i < compiler.unitsToProcess.length; i++) {
        if (compiler.unitsToProcess[i] != null) {
          if (compiler.unitsToProcess[i].compilationResult == result) {
            compiler.unitsToProcess[i] = null;
          }
        }
      }
    }
  }

  private List getBinarySourcesFrom(Map binarySourceEntries) {
    // Map is fileName |-> List<UnwovenClassFile>
    List ret = new ArrayList();
    for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
      String sourceFileName = (String) binIter.next();
      List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
      // XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
      CompilationResult result = new CompilationResult(sourceFileName.toCharArray(), 0, 0, Integer.MAX_VALUE);
      result.noSourceAvailable();
      InterimCompilationResult binarySource = new InterimCompilationResult(result, unwovenClassFiles);
      ret.add(binarySource);
    }
    return ret;
  }

  private void notifyRequestor() {
    for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
      InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
      compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
    }
  }

  private void weave() throws IOException {
    // ensure weaver state is set up correctly
    for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
      InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
      for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
        weaver.addClassFile(iresult.unwovenClassFiles()[i], false);
      }
    }

    weaver.setIsBatchWeave(isBatchCompile);
    weaver.prepareForWeave();
    if (weaver.needToReweaveWorld()) {
      if (!isBatchCompile) {
        // force full recompilation from source
        this.incrementalCompilationState.forceBatchBuildNextTimeAround();
        return;
        // addAllKnownClassesToWeaveList(); // if it's batch, they're already on the list...
      }
      resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
    } else {
      Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
      resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
    }

    // if (isBatchCompile) {
    // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
    // // passed into the compiler, the set of classes in injars and inpath...
    // } else if (weaver.needToReweaveWorld()) {
    // addAllKnownClassesToWeaveList();
    // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
    // }
    try {
      weaver.weave(new WeaverAdapter(this, weaverMessageHandler, progressListener));
    } finally {
      // ???: is this the right point for this? After weaving has finished clear the caches.
      weaverMessageHandler.setCurrentResult(null);
      weaver.allWeavingComplete();
      weaver.tidyUp();
      IMessageHandler imh = weaver.getWorld().getMessageHandler();
      if (imh instanceof WeaverMessageHandler) {
        ((WeaverMessageHandler) imh).resetCompiler(null);
      }
    }
  }

  public void afterDietParsing(CompilationUnitDeclaration[] units) {
    // to be filled in...
  }

  public List getResultsPendingWeave() {
    return resultsPendingWeave;
  }

}
TOP

Related Classes of org.aspectj.ajdt.internal.compiler.AjCompilerAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.