use of com.sun.tools.apt.util.Bark in project ceylon-compiler by ceylon.
the class Apt method main.
public void main(com.sun.tools.javac.util.List<JCTree.JCCompilationUnit> treeList, ListBuffer<ClassSymbol> classes, Map<String, String> origOptions, ClassLoader aptCL, AnnotationProcessorFactory providedFactory, java.util.Set<Class<? extends AnnotationProcessorFactory>> productiveFactories) {
Bark bark = Bark.instance(context);
java.io.PrintWriter out = bark.warnWriter;
Options options = Options.instance(context);
Collection<TypeDeclaration> spectypedecls = new LinkedHashSet<TypeDeclaration>();
Collection<TypeDeclaration> typedecls = new LinkedHashSet<TypeDeclaration>();
Set<String> unmatchedAnnotations = new LinkedHashSet<String>();
Set<AnnotationTypeDeclaration> emptyATDS = Collections.emptySet();
Set<Class<? extends AnnotationProcessorFactory>> currentRoundFactories = new LinkedHashSet<Class<? extends AnnotationProcessorFactory>>();
// Determine what annotations are present on the input source
// files, create collections of specified type declarations,
// and type declarations.
AptTreeScanner ats = new AptTreeScanner();
for (JCTree t : treeList) {
t.accept(ats);
}
// Turn collection of ClassSymbols into Collection of apt decls
for (ClassSymbol cs : ats.specifiedDeclCollection) {
TypeDeclaration decl = aptenv.declMaker.getTypeDeclaration(cs);
spectypedecls.add(decl);
}
for (ClassSymbol cs : ats.declCollection) {
TypeDeclaration decl = aptenv.declMaker.getTypeDeclaration(cs);
typedecls.add(decl);
}
unmatchedAnnotations.addAll(ats.getAnnotationSet());
// Process input class files
for (ClassSymbol cs : classes) {
TypeDeclaration decl = aptenv.declMaker.getTypeDeclaration(cs);
// System.out.println("Adding a class to spectypedecls");
spectypedecls.add(decl);
typedecls.add(decl);
computeAnnotationSet(cs, unmatchedAnnotations);
}
if (options.get("-XListAnnotationTypes") != null) {
out.println("Set of annotations found:" + (new TreeSet<String>(unmatchedAnnotations)).toString());
}
AnnotationProcessorEnvironmentImpl trivAPE = new AnnotationProcessorEnvironmentImpl(spectypedecls, typedecls, origOptions, context);
if (options.get("-XListDeclarations") != null) {
out.println("Set of Specified Declarations:" + spectypedecls);
out.println("Set of Included Declarations: " + typedecls);
}
if (options.get("-print") != null) {
if (spectypedecls.size() == 0)
throw new UsageMessageNeededException();
// Run the printing processor
AnnotationProcessor proc = (new BootstrapAPF()).getProcessorFor(new HashSet<AnnotationTypeDeclaration>(), trivAPE);
proc.process();
} else {
// Discovery process
// List of annotation processory factory instances
java.util.Iterator<AnnotationProcessorFactory> providers = null;
{
/*
* If a factory is provided by the user, the
* "-factory" and "-factorypath" options are not used.
*
* Otherwise, if the "-factory" option is used, search
* the appropriate path for the named class.
* Otherwise, use sun.misc.Service to implement the
* default discovery policy.
*/
java.util.List<AnnotationProcessorFactory> list = new LinkedList<AnnotationProcessorFactory>();
String factoryName = options.get("-factory");
if (providedFactory != null) {
list.add(providedFactory);
providers = list.iterator();
} else if (factoryName != null) {
try {
AnnotationProcessorFactory factory = (AnnotationProcessorFactory) (aptCL.loadClass(factoryName).newInstance());
list.add(factory);
} catch (ClassNotFoundException cnfe) {
bark.aptWarning("FactoryNotFound", factoryName);
} catch (ClassCastException cce) {
bark.aptWarning("FactoryWrongType", factoryName);
} catch (Exception e) {
bark.aptWarning("FactoryCantInstantiate", factoryName);
} catch (Throwable t) {
throw new AnnotationProcessingError(t);
}
providers = list.iterator();
} else {
@SuppressWarnings("unchecked") Iterator<AnnotationProcessorFactory> iter = sun.misc.Service.providers(AnnotationProcessorFactory.class, aptCL);
providers = iter;
}
}
java.util.Map<AnnotationProcessorFactory, Set<AnnotationTypeDeclaration>> factoryToAnnotation = new LinkedHashMap<AnnotationProcessorFactory, Set<AnnotationTypeDeclaration>>();
if (!providers.hasNext() && productiveFactories.size() == 0) {
if (unmatchedAnnotations.size() > 0)
bark.aptWarning("NoAnnotationProcessors");
if (spectypedecls.size() == 0)
throw new UsageMessageNeededException();
// no processors; nothing else to do
return;
} else {
if (unmatchedAnnotations.size() == 0)
unmatchedAnnotations.add("");
Set<String> emptyStringSet = new HashSet<String>();
emptyStringSet.add("");
emptyStringSet = Collections.unmodifiableSet(emptyStringSet);
while (providers.hasNext()) {
Object provider = providers.next();
try {
Set<String> matchedStrings = new HashSet<String>();
AnnotationProcessorFactory apf = (AnnotationProcessorFactory) provider;
Collection<String> supportedTypes = apf.supportedAnnotationTypes();
Collection<Pattern> supportedTypePatterns = new LinkedList<Pattern>();
for (String s : supportedTypes) supportedTypePatterns.add(importStringToPattern(s));
for (String s : unmatchedAnnotations) {
for (Pattern p : supportedTypePatterns) {
if (p.matcher(s).matches()) {
matchedStrings.add(s);
break;
}
}
}
unmatchedAnnotations.removeAll(matchedStrings);
if (options.get("-XPrintFactoryInfo") != null) {
out.println("Factory " + apf.getClass().getName() + " matches " + ((matchedStrings.size() == 0) ? "nothing." : matchedStrings));
}
if (matchedStrings.size() > 0) {
// convert annotation names to annotation
// type decls
Set<AnnotationTypeDeclaration> atds = new HashSet<AnnotationTypeDeclaration>();
// annotation type declarations.
if (!matchedStrings.equals(emptyStringSet)) {
for (String s : matchedStrings) {
TypeDeclaration decl = aptenv.declMaker.getTypeDeclaration(s);
AnnotationTypeDeclaration annotdecl;
if (decl == null) {
bark.aptError("DeclarationCreation", s);
} else {
try {
annotdecl = (AnnotationTypeDeclaration) decl;
atds.add(annotdecl);
} catch (ClassCastException cce) {
bark.aptError("BadDeclaration", s);
}
}
}
}
currentRoundFactories.add(apf.getClass());
productiveFactories.add(apf.getClass());
factoryToAnnotation.put(apf, atds);
} else if (productiveFactories.contains(apf.getClass())) {
// If a factory provided a processor in a
// previous round but doesn't match any
// annotations this round, call it with an
// empty set of declarations.
currentRoundFactories.add(apf.getClass());
factoryToAnnotation.put(apf, emptyATDS);
}
if (unmatchedAnnotations.size() == 0)
break;
} catch (ClassCastException cce) {
bark.aptWarning("BadFactory", cce);
}
}
unmatchedAnnotations.remove("");
}
// If the set difference of productiveFactories and
// currentRoundFactories is non-empty, call the remaining
// productive factories with an empty set of declarations.
{
java.util.Set<Class<? extends AnnotationProcessorFactory>> neglectedFactories = new LinkedHashSet<Class<? extends AnnotationProcessorFactory>>(productiveFactories);
neglectedFactories.removeAll(currentRoundFactories);
for (Class<? extends AnnotationProcessorFactory> working : neglectedFactories) {
try {
AnnotationProcessorFactory factory = working.newInstance();
factoryToAnnotation.put(factory, emptyATDS);
} catch (Exception e) {
bark.aptWarning("FactoryCantInstantiate", working.getName());
} catch (Throwable t) {
throw new AnnotationProcessingError(t);
}
}
}
if (unmatchedAnnotations.size() > 0)
bark.aptWarning("AnnotationsWithoutProcessors", unmatchedAnnotations);
Set<AnnotationProcessor> processors = new LinkedHashSet<AnnotationProcessor>();
// make sure the usage message is printed
if (spectypedecls.size() == 0 && factoryToAnnotation.keySet().size() == 0)
throw new UsageMessageNeededException();
try {
for (Map.Entry<AnnotationProcessorFactory, Set<AnnotationTypeDeclaration>> entry : factoryToAnnotation.entrySet()) {
AnnotationProcessorFactory apFactory = entry.getKey();
AnnotationProcessor processor = apFactory.getProcessorFor(entry.getValue(), trivAPE);
if (processor != null)
processors.add(processor);
else
bark.aptWarning("NullProcessor", apFactory.getClass().getName());
}
} catch (Throwable t) {
throw new AnnotationProcessingError(t);
}
LinkedList<AnnotationProcessor> temp = new LinkedList<AnnotationProcessor>();
temp.addAll(processors);
AnnotationProcessor proc = AnnotationProcessors.getCompositeAnnotationProcessor(temp);
try {
proc.process();
} catch (Throwable t) {
throw new AnnotationProcessingError(t);
}
// Invoke listener callback mechanism
trivAPE.roundComplete();
FilerImpl filerimpl = (FilerImpl) trivAPE.getFiler();
genSourceFileNames = filerimpl.getSourceFileNames();
genClassFileNames = filerimpl.getClassFileNames();
// Make sure new files are written out
filerimpl.flush();
}
}
use of com.sun.tools.apt.util.Bark 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;
}
use of com.sun.tools.apt.util.Bark in project ceylon-compiler by ceylon.
the class Apt method importStringToPattern.
/**
* Convert import-style string to regex matching that string. If
* the string is a valid import-style string, return a regex that
* won't match anything.
*/
Pattern importStringToPattern(String s) {
if (com.sun.tools.javac.processing.JavacProcessingEnvironment.isValidImportString(s)) {
return com.sun.tools.javac.processing.JavacProcessingEnvironment.validImportStringToPattern(s);
} else {
Bark bark = Bark.instance(context);
bark.aptWarning("MalformedSupportedString", s);
return com.sun.tools.javac.processing.JavacProcessingEnvironment.noMatches;
}
}
Aggregations