Search in sources :

Example 1 with Bark

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();
    }
}
Also used : AnnotationProcessorEnvironmentImpl(com.sun.tools.apt.mirror.apt.AnnotationProcessorEnvironmentImpl) java.util(java.util) com.sun.tools.javac.util(com.sun.tools.javac.util) Bark(com.sun.tools.apt.util.Bark) FilerImpl(com.sun.tools.apt.mirror.apt.FilerImpl) AnnotationTypeDeclaration(com.sun.mirror.declaration.AnnotationTypeDeclaration) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) TypeDeclaration(com.sun.mirror.declaration.TypeDeclaration) AnnotationTypeDeclaration(com.sun.mirror.declaration.AnnotationTypeDeclaration)

Example 2 with Bark

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;
}
Also used : Bark(com.sun.tools.apt.util.Bark) UsageMessageNeededException(com.sun.tools.apt.comp.UsageMessageNeededException) URLClassLoader(java.net.URLClassLoader) JavaFileManager(javax.tools.JavaFileManager) IOException(java.io.IOException) JavacFileManager(com.sun.tools.javac.file.JavacFileManager) com.sun.tools.javac.util(com.sun.tools.javac.util) URLClassLoader(java.net.URLClassLoader) File(java.io.File)

Example 3 with Bark

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;
    }
}
Also used : Bark(com.sun.tools.apt.util.Bark)

Aggregations

Bark (com.sun.tools.apt.util.Bark)3 com.sun.tools.javac.util (com.sun.tools.javac.util)2 IOException (java.io.IOException)2 AnnotationTypeDeclaration (com.sun.mirror.declaration.AnnotationTypeDeclaration)1 TypeDeclaration (com.sun.mirror.declaration.TypeDeclaration)1 UsageMessageNeededException (com.sun.tools.apt.comp.UsageMessageNeededException)1 AnnotationProcessorEnvironmentImpl (com.sun.tools.apt.mirror.apt.AnnotationProcessorEnvironmentImpl)1 FilerImpl (com.sun.tools.apt.mirror.apt.FilerImpl)1 JavacFileManager (com.sun.tools.javac.file.JavacFileManager)1 File (java.io.File)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 URLClassLoader (java.net.URLClassLoader)1 java.util (java.util)1 JavaFileManager (javax.tools.JavaFileManager)1