use of com.sun.tools.apt.comp.UsageMessageNeededException in project ceylon-compiler by ceylon.
the class Main method compile.
/** Programmatic interface for main function.
* @param args The command line parameters.
*/
public int compile(String[] args, AnnotationProcessorFactory factory) {
int returnCode = 0;
providedFactory = factory;
Context context = new Context();
JavacFileManager.preRegister(context);
options = Options.instance(context);
Bark bark;
/*
* Process the command line options to create the intial
* options data. This processing is at least partially reused
* by any recursive apt calls.
*/
// For testing: assume all arguments in forcedOpts are
// prefixed to command line arguments.
processArgs(forcedOpts);
/*
* A run of apt only gets passed the most recently generated
* files; the initial run of apt gets passed the files from
* the command line.
*/
java.util.List<String> origFilenames;
try {
// assign args the result of parse to capture results of
// '@file' expansion
origFilenames = processArgs((args = CommandLine.parse(args)));
if (options.get("suppress-tool-api-removal-message") == null) {
Bark.printLines(out, getLocalizedString("misc.Deprecation"));
}
if (origFilenames == null) {
return EXIT_CMDERR;
} else if (origFilenames.size() == 0) {
// it is allowed to compile nothing if just asking for help
if (options.get("-help") != null || options.get("-X") != null)
return EXIT_OK;
}
} catch (java.io.FileNotFoundException e) {
Bark.printLines(out, ownName + ": " + getLocalizedString("err.file.not.found", e.getMessage()));
return EXIT_SYSERR;
} catch (IOException ex) {
ioMessage(ex);
return EXIT_SYSERR;
} catch (OutOfMemoryError ex) {
resourceMessage(ex);
return EXIT_SYSERR;
} catch (StackOverflowError ex) {
resourceMessage(ex);
return EXIT_SYSERR;
} catch (FatalError ex) {
feMessage(ex);
return EXIT_SYSERR;
} catch (sun.misc.ServiceConfigurationError sce) {
sceMessage(sce);
return EXIT_ABNORMAL;
} catch (Throwable ex) {
bugMessage(ex);
return EXIT_ABNORMAL;
}
boolean firstRound = true;
boolean needSourcePath = false;
boolean needClassPath = false;
boolean classesAsDecls = options.get("-XclassesAsDecls") != null;
/*
* Create augumented classpath and sourcepath values.
*
* If any of the prior apt rounds generated any new source
* files, the n'th apt round (and any javac invocation) has the
* source destination path ("-s path") as the last element of
* the "-sourcepath" to the n'th call.
*
* If any of the prior apt rounds generated any new class files,
* the n'th apt round (and any javac invocation) has the class
* destination path ("-d path") as the last element of the
* "-classpath" to the n'th call.
*/
String augmentedSourcePath = "";
String augmentedClassPath = "";
String baseClassPath = "";
try {
/*
* Record original options for future annotation processor
* invocations.
*/
origOptions = new HashMap<String, String>(options.size());
for (String s : options.keySet()) {
String value;
if (s.equals(value = options.get(s)))
origOptions.put(s, (String) null);
else
origOptions.put(s, value);
}
origOptions = Collections.unmodifiableMap(origOptions);
JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
{
// Note: it might be necessary to check for an empty
// component ("") of the source path or class path
String sourceDest = options.get("-s");
if (fm.hasLocation(StandardLocation.SOURCE_PATH)) {
for (File f : fm.getLocation(StandardLocation.SOURCE_PATH)) augmentedSourcePath += (f + File.pathSeparator);
augmentedSourcePath += (sourceDest == null) ? "." : sourceDest;
} else {
augmentedSourcePath = ".";
if (sourceDest != null)
augmentedSourcePath += (File.pathSeparator + sourceDest);
}
String classDest = options.get("-d");
if (fm.hasLocation(StandardLocation.CLASS_PATH)) {
for (File f : fm.getLocation(StandardLocation.CLASS_PATH)) baseClassPath += (f + File.pathSeparator);
// put baseClassPath into map to handle any
// value needed for the classloader
options.put("-classpath", baseClassPath);
augmentedClassPath = baseClassPath + ((classDest == null) ? "." : classDest);
} else {
baseClassPath = ".";
if (classDest != null)
augmentedClassPath = baseClassPath + (File.pathSeparator + classDest);
}
assert options.get("-classpath") != null;
}
/*
* Create base and augmented class loaders
*/
ClassLoader augmentedAptCL = null;
{
/*
* Use a url class loader to look for classes on the
* user-specified class path. Prepend computed bootclass
* path, which includes extdirs, to the URLClassLoader apt
* uses.
*/
String aptclasspath = "";
String bcp = "";
Iterable<? extends File> bootclasspath = fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
if (bootclasspath != null) {
for (File f : bootclasspath) bcp += (f + File.pathSeparator);
}
// If the factory path is set, use that path
if (providedFactory == null)
aptclasspath = options.get("-factorypath");
if (aptclasspath == null)
aptclasspath = options.get("-classpath");
assert aptclasspath != null;
aptclasspath = (bcp + aptclasspath);
aptCL = new URLClassLoader(pathToURLs(aptclasspath));
if (providedFactory == null && // same CL even if new class files written
options.get("-factorypath") != null)
augmentedAptCL = aptCL;
else {
// Create class loader in case new class files are
// written
augmentedAptCL = new URLClassLoader(pathToURLs(augmentedClassPath.substring(baseClassPath.length())), aptCL);
}
}
// For -XPrintAptRounds
int round = 0;
do {
round++;
Context newContext = new Context();
// creates a new context
Options newOptions = Options.instance(newContext);
newOptions.putAll(options);
// if genSource files, must add destination to source path
if (genSourceFileNames.size() > 0 && !firstRound) {
newOptions.put("-sourcepath", augmentedSourcePath);
needSourcePath = true;
}
aggregateGenSourceFileNames.addAll(genSourceFileNames);
sourceFileNames.addAll(genSourceFileNames);
genSourceFileNames.clear();
// "foo" to class path if any class files are generated
if (genClassFileNames.size() > 0) {
newOptions.put("-classpath", augmentedClassPath);
aptCL = augmentedAptCL;
needClassPath = true;
}
aggregateGenClassFileNames.addAll(genClassFileNames);
classFileNames.addAll(genClassFileNames);
genClassFileNames.clear();
options = newOptions;
if (options.get("-XPrintAptRounds") != null) {
out.println("apt Round : " + round);
out.println("filenames: " + sourceFileNames);
if (classesAsDecls)
out.println("classnames: " + classFileNames);
out.println("options: " + options);
}
returnCode = compile(args, newContext);
firstRound = false;
// Check for reported errors before continuing
bark = Bark.instance(newContext);
} while (((genSourceFileNames.size() != 0) || (classesAsDecls && genClassFileNames.size() != 0)) && bark.nerrors == 0);
} catch (UsageMessageNeededException umne) {
help();
// will cause usage message to be printed
return EXIT_CMDERR;
}
/*
* Do not compile if a processor has reported an error or if
* there are no source files to process. A more sophisticated
* test would also fail for syntax errors caught by javac.
*/
if (options.get("-nocompile") == null && options.get("-print") == null && bark.nerrors == 0 && (origFilenames.size() > 0 || aggregateGenSourceFileNames.size() > 0)) {
/*
* Need to create new argument string for calling javac:
* 1. apt specific arguments (e.g. -factory) must be stripped out
* 2. proper settings for sourcepath and classpath must be used
* 3. generated class names must be added
* 4. class file names as declarations must be removed
*/
int newArgsLength = args.length + (needSourcePath ? 1 : 0) + (needClassPath ? 1 : 0) + aggregateGenSourceFileNames.size();
// class names from the javac argument list
argLoop: for (int i = 0; i < args.length; i++) {
int matchPosition = -1;
// "-A" by itself is recognized by apt but not javac
if (args[i] != null && args[i].equals("-A")) {
newArgsLength--;
args[i] = null;
continue argLoop;
} else {
optionLoop: for (int j = 0; j < recognizedOptions.length; j++) {
if (args[i] != null && recognizedOptions[j].matches(args[i])) {
matchPosition = j;
break optionLoop;
}
}
if (matchPosition != -1) {
Option op = recognizedOptions[matchPosition];
if (op.aptOnly) {
newArgsLength--;
args[i] = null;
if (op.hasArg()) {
newArgsLength--;
args[i + 1] = null;
}
} else {
if (op.hasArg()) {
// skip over next string
i++;
continue argLoop;
}
if ((options.get("-XclassesAsDecls") != null) && (matchPosition == (recognizedOptions.length - 1))) {
// consideration by javac.
if (!args[i].endsWith(".java")) {
newArgsLength--;
args[i] = null;
}
}
}
}
}
}
String[] newArgs = new String[newArgsLength];
int j = 0;
for (int i = 0; i < args.length; i++) {
if (args[i] != null)
newArgs[j++] = args[i];
}
if (needClassPath)
newArgs[j++] = "-XD-classpath=" + augmentedClassPath;
if (needSourcePath) {
newArgs[j++] = "-XD-sourcepath=" + augmentedSourcePath;
for (String s : aggregateGenSourceFileNames) newArgs[j++] = s;
}
returnCode = com.sun.tools.javac.Main.compile(newArgs);
}
return returnCode;
}
Aggregations