BuildArgParser parser = new BuildArgParser(handler);
- AjBuildConfig config = new AjBuildConfig();
+ AjBuildConfig config = new AjBuildConfig(parser);
parser.populateBuildConfig(config, args, false, configFile);
package org.aspectj.ajdt.ajc;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.StringTokenizer;
-
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
-import org.aspectj.bridge.CountingMessageHandler;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.SourceLocation;
-import org.aspectj.bridge.Version;
+import org.aspectj.bridge.*;
+import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.batch.Main;
+import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.util.FileUtil;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.Dump;
import org.aspectj.weaver.WeaverMessages;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.*;
+
@SuppressWarnings("unchecked")
public class BuildArgParser extends Main {
* Overrides super's bundle.
*/
public BuildArgParser(PrintWriter writer, IMessageHandler handler) {
- super(writer, writer, false);
+ super(writer, writer, false, null, null);
if (writer instanceof StringPrintWriter) {
errorSink = ((StringPrintWriter) writer).stringWriter.getBuffer();
/**
* Generate build configuration for the input args, passing to handler any error messages.
- *
+ *
* @param args the String[] arguments for the build configuration
* @return AjBuildConfig per args, which will be invalid unless there are no handler errors.
*/
public AjBuildConfig genBuildConfig(String[] args) {
- AjBuildConfig config = new AjBuildConfig();
+ final AjBuildConfig config = new AjBuildConfig(this);
populateBuildConfig(config, args, true, null);
return config;
}
/**
* Generate build configuration for the input arguments, passing to handler any error messages.
- *
+ *
* @param args the String[] arguments for the build configuration
* @param setClasspath determines if the classpath should be parsed and set on the build configuration
* @param configFile can be null
// without these it will go searching for reasonable values from properties
// TODO fix org.eclipse.jdt.internal.compiler.batch.Main so this hack isn't needed
javaArgList.add("-classpath");
- javaArgList.add(System.getProperty("user.dir"));
+ javaArgList.add(parser.classpath == null ? System.getProperty("user.dir") : parser.classpath);
javaArgList.add("-bootclasspath");
- javaArgList.add(System.getProperty("user.dir"));
+ javaArgList.add(parser.bootclasspath == null ? System.getProperty("user.dir") : parser.bootclasspath);
javaArgList.addAll(parser.getUnparsedArgs());
super.configure(javaArgList.toArray(new String[javaArgList.size()]));
System.out.println(version);
}
+ @Override
+ public void addExtraProblems(CategorizedProblem problem) {
+ super.addExtraProblems(problem);
+ if (problem instanceof AptProblem) {
+ handler.handleMessage(newAptMessage((AptProblem)problem));
+ }
+ }
+
+ private IMessage newAptMessage(AptProblem problem) {
+ String message = problem.getMessage();
+ boolean isError = problem.isError();
+ if (problem._referenceContext != null) {
+ return new Message(message,
+ new EclipseSourceLocation(problem._referenceContext.compilationResult(), problem.getSourceStart(), problem.getSourceEnd()),
+ isError);
+ } else {
+ return new Message(message, null, isError);
+ }
+ }
+
+ @Override
+ public void initializeAnnotationProcessorManager() {
+ if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_6 || !this.compilerOptions.processAnnotations)
+ return;
+ super.initializeAnnotationProcessorManager();
+ }
+
+ @Override
public void printUsage() {
System.out.println(getUsage());
System.out.flush();
/**
* Get messages not dumped to handler or any PrintWriter.
- *
+ *
* @param flush if true, empty errors
* @return null if none, String otherwise
* @see BuildArgParser()
// dirLookahead(arg, args, nextArgIndex);
} else if (arg.equals("-proceedOnError")) {
buildConfig.setProceedOnError(true);
+ } else if (arg.equals("-processorpath")) { // -processorpath <directories and ZIP archives separated by pathseporator
+ addPairToUnparsed(args, arg, nextArgIndex, "-processorpath requires list of external directories or zip archives");
+ } else if (arg.equals("-processor")) { // -processor <class1[,class2,...]>
+ addPairToUnparsed(args, arg, nextArgIndex, "-processor requires list of processors' classes");
+ } else if (arg.equals("-s")) { // -s <dir> destination directory for generated source files
+ addPairToUnparsed(args, arg, nextArgIndex, "-s requires directory");
+ } else if (arg.equals("-classNames")) { // -classNames <className1[,className2,...]>
+ addPairToUnparsed(args, arg, nextArgIndex, "-classNames requires list of classes");
+ } else
+ // if you want to run ajc compiler in Intellij Idea you have to add jvm arg "-XXproc:ignore" for getting atp to work
+ if (arg.equals("-XXproc:ignore")) { // TODO(yshkvoskiy): remove it when IDEA will support correct 'proc' parameters
+ for (final Iterator<Arg> i = args.iterator(); i.hasNext(); ) {
+ if (i.next().getValue().startsWith("-proc:"))
+ i.remove();
+ }
+ for (final Iterator<String> i = unparsedArgs.iterator(); i.hasNext(); ) {
+ if (i.next().startsWith("-proc:"))
+ i.remove();
+ }
} else if (new File(arg).isDirectory()) {
showError("dir arg not permitted: " + arg);
} else if (arg.startsWith("-Xajruntimetarget")) {
return new File(dir, name);
}
+ private void addPairToUnparsed(LinkedList<Arg> args, String arg, int nextArgIndex, String errorMessage) {
+ if (args.size() <= nextArgIndex) {
+ showError(errorMessage);
+ return;
+ }
+ final Arg nextArg = args.get(nextArgIndex);
+ args.remove(nextArg);
+ unparsedArgs.add(arg);
+ unparsedArgs.add(nextArg.getValue());
+ }
+
+ private int indexOf(LinkedList<Arg> args, String arg) {
+ int index = 0;
+ for (Arg argument : args) {
+ if (arg.equals(argument.getValue())) {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
+
}
}
import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-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.LocalTypeBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.ConcreteTypeMunger;
/**
* Overrides the default eclipse LookupEnvironment for two purposes.
- *
+ *
* 1. To provide some additional phases to <code>completeTypeBindings</code> that weave declare parents and inter-type declarations
* at the correct time.
- *
+ *
* 2. To intercept the loading of new binary types to ensure the they will have declare parents and inter-type declarations woven
* when appropriate.
- *
+ *
* @author Jim Hugunin
*/
public class AjLookupEnvironment extends LookupEnvironment implements AnonymousClassCreationListener {
factory.finishTypeMungers();
// now do weaving
- List<ConcreteTypeMunger> typeMungers = factory.getTypeMungers();
+ final List<ConcreteTypeMunger> typeMungers = factory.getTypeMungers();
- List<DeclareParents> declareParents = factory.getDeclareParents();
- List<DeclareAnnotation> declareAnnotationOnTypes = factory.getDeclareAnnotationOnTypes();
+ final List<DeclareParents> declareParents = factory.getDeclareParents();
+ final List<DeclareAnnotation> declareAnnotationOnTypes = factory.getDeclareAnnotationOnTypes();
doPendingWeaves();
AsmManager.setCompletingTypeBindings(false);
factory.getWorld().getCrosscuttingMembersSet().verify();
CompilationAndWeavingContext.leavingPhase(completeTypeBindingsToken);
+
+ if (isProcessingAnnotations) {
+ throw new SourceTypeCollisionException(); // TODO(yushkovskiy): temporary solution; forcing to recompile units to insert mungers into types
+ }
}
// /**
// }
// }
- public void doSupertypesFirst(ReferenceBinding rb, Collection yetToProcess) {
+ public void doSupertypesFirst(ReferenceBinding rb, Collection<? extends ReferenceBinding> yetToProcess) {
if (rb instanceof SourceTypeBinding) {
if (yetToProcess.contains(rb)) {
collectAllITDsAndDeclares((SourceTypeBinding) rb, yetToProcess);
/**
* Find all the ITDs and Declares, but it is important we do this from the supertypes down to the subtypes.
- *
+ *
* @param sourceType
* @param yetToProcess
*/
- private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection yetToProcess) {
+ private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection<? extends ReferenceBinding> yetToProcess) {
// Look at the supertype first
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES,
sourceType.sourceName);
* compile... it stops recursing the first time it hits a type we aren't going to process during this compile. This could cause
* problems if you supply 'pieces' of a hierarchy, i.e. the bottom and the top, but not the middle - but what the hell are you
* doing if you do that?
- *
+ *
* @param mode 0=do everything, 1=do declare parents, 2=do ITDs
*/
private void weaveIntertypes(List<SourceTypeBinding> typesToProcess, SourceTypeBinding typeToWeave,
}
}
- List forRemoval = new ArrayList();
+ List<Object> forRemoval = new ArrayList<Object>();
// now lets loop over and over until we have done all we can
while ((anyNewAnnotations || anyNewParents) && (!decpToRepeat.isEmpty() || !decaToRepeat.isEmpty())) {
anyNewParents = anyNewAnnotations = false;
/**
* Called when we discover we are weaving intertype declarations on some type that has an existing 'WeaverStateInfo' object -
* this is typically some previously woven type that has been passed on the inpath.
- *
+ *
* sourceType and onType are the 'same type' - the former is the 'Eclipse' version and the latter is the 'Weaver' version.
*/
private void processTypeMungersFromExistingWeaverState(SourceTypeBinding sourceType, ResolvedType onType) {
// AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(
// decA.getSourceLocation(), rtx.getSourceLocation());
- Annotation abefore[] = sourceType.scope.referenceContext.annotations;
- Annotation[] newset = new Annotation[toAdd.length + (abefore == null ? 0 : abefore.length)];
+ final Annotation[] abefore = sourceType.scope.referenceContext.annotations;
+ final Annotation[] newset = new Annotation[toAdd.length + (abefore == null ? 0 : abefore.length)];
System.arraycopy(toAdd, 0, newset, 0, toAdd.length);
if (abefore != null) {
System.arraycopy(abefore, 0, newset, toAdd.length, abefore.length);
/**
* Callback driven when the compiler detects an anonymous type during block resolution. We need to add it to the weaver so that
* we don't trip up later.
- *
+ *
* @param aBinding
*/
public void anonymousTypeBindingCreated(LocalTypeBinding aBinding) {
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
+import org.aspectj.ajdt.ajc.BuildArgParser;
import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.util.FileUtil;
private int changes = EVERYTHING; // bitflags, see CompilerConfigurationChangeFlags
- private AjCompilerOptions options;
+ private final AjCompilerOptions options;
+
+ private final BuildArgParser buildArgParser;
// incremental variants handled by the compiler client, but parsed here
private boolean incrementalMode;
* and enh. 29769. The settings here are duplicated from those set in org.eclipse.jdt.internal.compiler.batch.Main, but I've
* elected to copy them rather than refactor the JDT class since this keeps integration with future JDT releases easier (?).
*/
- public AjBuildConfig() {
+ public AjBuildConfig(BuildArgParser buildArgParser) {
+ this.buildArgParser = buildArgParser;
options = new AjCompilerOptions();
}
+ public BuildArgParser getBuildArgParser() {
+ return buildArgParser;
+ }
+
/**
* returned files includes
* <ul>
* <li>files listed by reference in argument list files</li>
* <li>files contained in sourceRootDir if that exists</li>
* </ul>
- *
+ *
* @return all source files that should be compiled.
*/
public List<File> getFiles() {
* <li>this only sets one of outputDir and outputJar as needed</li>
* <ul>
* This also configures super if javaOptions change.
- *
+ *
* @param global the AjBuildConfig to read globals from
*/
public void installGlobals(AjBuildConfig global) { // XXX relies on default values
public String getLintMode() {
return lintMode;
}
-
+
public Map<String,String> getLintOptionsMap() {
return lintOptionsMap;
}
/**
* Indicates what has changed in this configuration compared to the last time it was used, allowing the state management logic
* to make intelligent optimizations and skip unnecessary work.
- *
+ *
* @param changes set of bitflags, see {@link CompilerConfigurationChangeFlags} for flags
*/
public void setChanged(int changes) {
/**
* Return the bit flags indicating what has changed since the last time this config was used.
- *
+ *
* @return the bitflags according too {@link CompilerConfigurationChangeFlags}
*/
public int getChanged() {
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
+import org.aspectj.ajdt.ajc.BuildArgParser;
import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter;
import org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter;
import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.aspectj.org.eclipse.jdt.internal.compiler.impl.IrritantSet;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
private boolean batchCompile = true;
private INameEnvironment environment;
- private Map /* String -> List<UCF> */binarySourcesForTheNextCompile = new HashMap();
+ private Map<String, List<UnwovenClassFile>> /* String -> List<UCF> */binarySourcesForTheNextCompile = new HashMap<String, List<UnwovenClassFile>>();
// FIXME asc should this really be in here?
// private AsmManager structureModel;
/**
* Enable check for runtime version, used only by Ant/command-line Main.
- *
- * @param main Main unused except to limit to non-null clients.
+ *
+ * @param caller Main unused except to limit to non-null clients.
*/
public static void enableRuntimeVersionCheck(Main caller) {
DO_RUNTIME_VERSION_CHECK = null != caller;
/**
* Perform a build.
- *
+ *
* @return true if the build was successful (ie. no errors)
*/
private boolean performBuild(AjBuildConfig buildConfig, IMessageHandler baseHandler, boolean isFullBuild) throws IOException,
((ILifecycleAware) baseHandler).buildStarting(!isFullBuild);
}
CompilationAndWeavingContext.reset();
- int phase = isFullBuild ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD;
- ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase, buildConfig);
+ final int phase = isFullBuild ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD;
+ final ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase, buildConfig);
try {
if (isFullBuild) {
this.state = new AjState(this);
this.state.setCouldBeSubsequentIncrementalBuild(this.environmentSupportsIncrementalCompilation);
- boolean canIncremental = state.prepareForNextBuild(buildConfig);
+ final boolean canIncremental = state.prepareForNextBuild(buildConfig);
if (!canIncremental && !isFullBuild) { // retry as batch?
CompilationAndWeavingContext.leavingPhase(ct);
if (state.listenerDefined()) {
if (buildConfig == null || buildConfig.isCheckRuntimeVersion()) {
if (DO_RUNTIME_VERSION_CHECK) {
- String check = checkRtJar(buildConfig);
+ final String check = checkRtJar(buildConfig);
if (check != null) {
if (FAIL_IF_RUNTIME_NOT_FOUND) {
MessageUtil.error(handler, check);
// for bug 113554: support ajsym file generation for command line builds
if (buildConfig.isGenerateCrossRefsMode()) {
- File configFileProxy = new File(buildConfig.getOutputDir(), CROSSREFS_FILE_NAME);
+ final File configFileProxy = new File(buildConfig.getOutputDir(), CROSSREFS_FILE_NAME);
state.getStructureModel().writeStructureModel(configFileProxy.getAbsolutePath());
}
}
ret = !handler.hasErrors();
if (getBcelWorld() != null) {
- BcelWorld bcelWorld = getBcelWorld();
+ final BcelWorld bcelWorld = getBcelWorld();
bcelWorld.reportTimers();
bcelWorld.tidyUp();
}
/**
* Open an output jar file in which to write the compiler output.
- *
+ *
* @param outJar the jar file to open
* @return true if successful
*/
/**
* Add a directory entry to the output zip file. Don't do anything if not writing out to a zip file. A directory entry is one
* whose filename ends with '/'
- *
+ *
* @param directory the directory path
* @param srcloc the src of the directory entry, for use when creating a warning message
* @throws IOException if something goes wrong creating the new zip entry
/**
* Responsible for managing the ASM model between builds. Contains the policy for maintaining the persistance of elements in the
* model.
- *
+ *
* This code is driven before each 'fresh' (batch) build to create a new model.
*/
private void setupModel(AjBuildConfig config) {
}
org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(this);
- org.aspectj.org.eclipse.jdt.internal.compiler.Compiler compiler = new org.aspectj.org.eclipse.jdt.internal.compiler.Compiler(
- environment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), buildConfig.getOptions().getMap(),
- getBatchRequestor(), getProblemFactory());
-
+ final Map<?, ?> settings = buildConfig.getOptions().getMap();
+ final BuildArgParser bMain = buildConfig.getBuildArgParser();
+
+ final org.aspectj.org.eclipse.jdt.internal.compiler.Compiler compiler = new org.aspectj.org.eclipse.jdt.internal.compiler.Compiler(
+ environment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), settings,
+ getBatchRequestor(), getProblemFactory());
+ bMain.compilerOptions = compiler.options;
+ bMain.batchCompiler = compiler;
+ bMain.initializeAnnotationProcessorManager();
compiler.options.produceReferenceInfo = true; // TODO turn off when not needed
try {
public ICompilerRequestor getBatchRequestor() {
return new ICompilerRequestor() {
-
+ @Override
public void acceptResult(CompilationResult unitResult) {
// end of compile, must now write the results to the output destination
// this is either a jar file or a file in a directory
/*
* (non-Javadoc)
- *
+ *
* @see org.aspectj.ajdt.internal.compiler.AjCompiler.IOutputClassFileNameProvider#getOutputClassFileName(char[])
*/
public String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result) {
/*
* (non-Javadoc)
- *
+ *
* @see org.eclipse.jdt.internal.compiler.ICompilerAdapterFactory#getAdapter(org.eclipse.jdt.internal.compiler.Compiler)
*/
public ICompilerAdapter getAdapter(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) {
/**
* Some AspectJ lint options need to be known about in the compiler. This is how we pass them over...
- *
+ *
* @param forCompiler
*/
private void populateCompilerOptionsFromLintSettings(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) {
/*
* (non-Javadoc)
- *
+ *
* @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave()
*/
- public Map getBinarySourcesForThisWeave() {
+ public Map<String, List<UnwovenClassFile>> getBinarySourcesForThisWeave() {
return binarySourcesForTheNextCompile;
}
* 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.core.builder;
+import junit.framework.TestCase;
+import org.aspectj.ajdt.ajc.BuildArgParser;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import junit.framework.TestCase;
-
public class AjStateTest extends TestCase {
private AjState aRightState;
protected void setUp() throws Exception {
super.setUp();
aRightState = new AjState(null);
- oldConfig = new AjBuildConfig();
- newConfig = new AjBuildConfig();
+ final BuildArgParser parser = new BuildArgParser(new IMessageHandler() {
+ @Override
+ public boolean handleMessage(IMessage message) throws AbortException {
+ return true;
+ }
+
+ @Override
+ public boolean isIgnoring(IMessage.Kind kind) {
+ return false;
+ }
+
+ @Override
+ public void dontIgnore(IMessage.Kind kind) {
+ }
+
+ @Override
+ public void ignore(IMessage.Kind kind) {
+ }
+ });
+ oldConfig = new AjBuildConfig(parser);
+ newConfig = new AjBuildConfig(parser);
List<String> cp = new ArrayList<String>();
cp.add("adir");
cp.add("ajar.jar");