Search in sources :

Example 1 with RoundEnvironment

use of javax.annotation.processing.RoundEnvironment in project javapoet by square.

the class AbstractTypesTest method errorTypes.

@Test
public void errorTypes() {
    JavaFileObject hasErrorTypes = JavaFileObjects.forSourceLines("com.squareup.tacos.ErrorTypes", "package com.squareup.tacos;", "", "@SuppressWarnings(\"hook-into-compiler\")", "class ErrorTypes {", "  Tacos tacos;", "  Ingredients.Guacamole guacamole;", "}");
    Compilation compilation = javac().withProcessors(new AbstractProcessor() {

        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            TypeElement classFile = processingEnv.getElementUtils().getTypeElement("com.squareup.tacos.ErrorTypes");
            List<VariableElement> fields = fieldsIn(classFile.getEnclosedElements());
            ErrorType topLevel = (ErrorType) fields.get(0).asType();
            ErrorType member = (ErrorType) fields.get(1).asType();
            assertThat(TypeName.get(topLevel)).isEqualTo(ClassName.get("", "Tacos"));
            assertThat(TypeName.get(member)).isEqualTo(ClassName.get("Ingredients", "Guacamole"));
            return false;
        }

        @Override
        public Set<String> getSupportedAnnotationTypes() {
            return Collections.singleton("*");
        }
    }).compile(hasErrorTypes);
    assertThat(compilation).failed();
}
Also used : RoundEnvironment(javax.annotation.processing.RoundEnvironment) JavaFileObject(javax.tools.JavaFileObject) Compilation(com.google.testing.compile.Compilation) Set(java.util.Set) ErrorType(javax.lang.model.type.ErrorType) TypeElement(javax.lang.model.element.TypeElement) AbstractProcessor(javax.annotation.processing.AbstractProcessor) VariableElement(javax.lang.model.element.VariableElement) Test(org.junit.Test)

Example 2 with RoundEnvironment

use of javax.annotation.processing.RoundEnvironment in project Nucleus by NucleusPowered.

the class StoreProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    Map<Element, String> classes = new HashMap<>();
    Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Store.class);
    for (Element element : elements) {
        // Only storing classes.
        if (element.getKind().isClass()) {
            Store s = element.getAnnotation(Store.class);
            classes.put(element, s.isRoot() ? null : s.value());
        }
    }
    // Get the root elements
    ClassElementVisitor cev = new ClassElementVisitor();
    Map<String, String> conv = classes.entrySet().stream().filter(x -> x.getValue() == null).map(x -> cev.visit(x.getKey(), true)).filter(Objects::nonNull).collect(Collectors.toMap(x -> x.pa, x -> x.cl));
    final Map<String, Map<String, List<String>>> result = conv.values().stream().collect(Collectors.toMap(x -> x, x -> new HashMap<>()));
    classes.entrySet().stream().filter(x -> x.getValue() != null).map(x -> {
        StringTuple st = cev.visit(x.getKey(), false);
        if (st != null) {
            return new StringTuple(x.getValue(), st.cl);
        }
        return null;
    }).filter(Objects::nonNull).forEach(x -> {
        // Check the class vs package name
        conv.entrySet().stream().filter(y -> x.cl.startsWith(y.getKey())).distinct().findFirst().ifPresent(y -> result.get(y.getValue()).computeIfAbsent(x.pa, z -> new ArrayList<>()).add(x.cl));
    });
    if (!classes.isEmpty()) {
        // Write this file
        try {
            FileObject fo = this.processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "assets.nucleus", "classes.json");
            try (Writer os = fo.openWriter()) {
                os.write(new GsonBuilder().setPrettyPrinting().create().toJson(result));
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return false;
}
Also used : PackageElement(javax.lang.model.element.PackageElement) AbstractProcessor(javax.annotation.processing.AbstractProcessor) Modifier(javax.lang.model.element.Modifier) VariableElement(javax.lang.model.element.VariableElement) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) GsonBuilder(com.google.gson.GsonBuilder) ArrayList(java.util.ArrayList) FileObject(javax.tools.FileObject) SupportedSourceVersion(javax.annotation.processing.SupportedSourceVersion) Map(java.util.Map) AbstractElementVisitor8(javax.lang.model.util.AbstractElementVisitor8) Nullable(javax.annotation.Nullable) StandardLocation(javax.tools.StandardLocation) ExecutableElement(javax.lang.model.element.ExecutableElement) Set(java.util.Set) IOException(java.io.IOException) Element(javax.lang.model.element.Element) Processor(javax.annotation.processing.Processor) Collectors(java.util.stream.Collectors) TypeParameterElement(javax.lang.model.element.TypeParameterElement) Objects(java.util.Objects) SourceVersion(javax.lang.model.SourceVersion) List(java.util.List) RoundEnvironment(javax.annotation.processing.RoundEnvironment) AutoService(com.google.auto.service.AutoService) Writer(java.io.Writer) HashMap(java.util.HashMap) GsonBuilder(com.google.gson.GsonBuilder) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) TypeParameterElement(javax.lang.model.element.TypeParameterElement) IOException(java.io.IOException) FileObject(javax.tools.FileObject) HashMap(java.util.HashMap) Map(java.util.Map) Writer(java.io.Writer)

Example 3 with RoundEnvironment

use of javax.annotation.processing.RoundEnvironment in project requery by requery.

the class EntityProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    // types to generate in this round
    Map<TypeElement, EntityElement> entities = new HashMap<>();
    Types types = processingEnv.getTypeUtils();
    Set<TypeElement> annotationElements = new LinkedHashSet<>(annotations);
    for (TypeElement annotation : annotationElements) {
        for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
            typeElementOf(element).ifPresent(typeElement -> {
                EntityElement entity = null;
                if (isEntity(typeElement)) {
                    // create or get the entity for the annotation
                    entity = computeType(entities, typeElement);
                    // create or get the graph for it
                    String model = entity.modelName();
                    graphs.computeIfAbsent(model, key -> new EntityGraph(types, embeddedTypes)).add(entity);
                } else if (isSuperclass(typeElement)) {
                    entity = computeType(superTypes, typeElement);
                } else if (isEmbeddable(typeElement)) {
                    entity = computeType(embeddedTypes, typeElement);
                }
                if (entity != null) {
                    entity.addAnnotationElement(annotation, element);
                }
            });
        }
    }
    // process
    boolean hasErrors = false;
    Set<ElementValidator> validators = new LinkedHashSet<>();
    Elements elements = processingEnv.getElementUtils();
    for (EntityElement entity : entities.values()) {
        // add the annotated elements from the super type (if any)
        if (entity.element().getKind() == ElementKind.INTERFACE) {
            Queue<TypeMirror> interfaces = new LinkedList<>(entity.element().getInterfaces());
            while (!interfaces.isEmpty()) {
                TypeMirror mirror = interfaces.remove();
                TypeElement superElement = elements.getTypeElement(mirror.toString());
                if (superElement != null) {
                    mergeSuperType(entity, superElement);
                    interfaces.addAll(superElement.getInterfaces());
                }
            }
        }
        TypeMirror typeMirror = entity.element().getSuperclass();
        while (typeMirror.getKind() != TypeKind.NONE) {
            TypeElement superElement = elements.getTypeElement(typeMirror.toString());
            if (superElement != null) {
                mergeSuperType(entity, superElement);
                typeMirror = superElement.getSuperclass();
            } else {
                break;
            }
        }
        // process the entity
        Set<ElementValidator> results = entity.process(processingEnv);
        validators.addAll(results);
    }
    for (EntityElement entity : embeddedTypes.values()) {
        Set<ElementValidator> results = entity.process(processingEnv);
        validators.addAll(results);
    }
    for (EntityGraph graph : graphs.values()) {
        EntityGraphValidator validator = new EntityGraphValidator(processingEnv, graph);
        Set<ElementValidator> results = validator.validate();
        validators.addAll(results);
    }
    if (ElementValidator.hasErrors(validators)) {
        hasErrors = true;
        StringBuilder sb = new StringBuilder("Model has error(s) code generation may fail: ");
        validators.forEach(validator -> sb.append(validator.toString()));
        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, sb);
    }
    // generate
    Set<SourceGenerator> generators = new LinkedHashSet<>();
    if (!hasErrors || getOption(GENERATE_ALWAYS, true)) {
        for (EntityDescriptor entity : entities.values()) {
            EntityGraph graph = graphs.get(entity.modelName());
            if (graph != null) {
                generators.add(new EntityGenerator(processingEnv, graph, entity, null));
            }
        }
    }
    if (getOption(GENERATE_MODEL, true)) {
        Map<String, Collection<EntityDescriptor>> packagesMap = new LinkedHashMap<>();
        Set<EntityDescriptor> allEntities = graphs.values().stream().flatMap(graph -> graph.entities().stream()).collect(Collectors.toSet());
        for (EntityDescriptor entity : allEntities) {
            EntityGraph graph = graphs.get(entity.modelName());
            String packageName = findModelPackageName(graph);
            packagesMap.computeIfAbsent(packageName, key -> new LinkedHashSet<>());
            packagesMap.get(packageName).addAll(graph.entities());
        }
        for (EntityDescriptor entity : entities.values()) {
            EntityGraph graph = graphs.get(entity.modelName());
            String packageName = findModelPackageName(graph);
            if (entity.generatesAdditionalTypes()) {
                packagesMap.remove(packageName);
            }
        }
        generators.addAll(packagesMap.entrySet().stream().filter(entry -> !entry.getValue().isEmpty()).filter(entry -> !generatedModelPackages.contains(entry.getKey())).peek(entry -> generatedModelPackages.add(entry.getKey())).map(entry -> new ModelGenerator(processingEnv, entry.getKey(), entry.getValue())).collect(Collectors.toList()));
    }
    for (SourceGenerator generator : generators) {
        try {
            generator.generate();
        } catch (IOException e) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
        }
    }
    return false;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) AbstractProcessor(javax.annotation.processing.AbstractProcessor) SupportedOptions(javax.annotation.processing.SupportedOptions) TypeElement(javax.lang.model.element.TypeElement) HashMap(java.util.HashMap) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Elements(javax.lang.model.util.Elements) GENERATE_MODEL(io.requery.processor.EntityProcessor.GENERATE_MODEL) TreeSet(java.util.TreeSet) LinkedHashMap(java.util.LinkedHashMap) Embedded(io.requery.Embedded) Diagnostic(javax.tools.Diagnostic) Map(java.util.Map) LinkedList(java.util.LinkedList) GENERATE_JPA(io.requery.processor.EntityProcessor.GENERATE_JPA) LinkedHashSet(java.util.LinkedHashSet) Entity(io.requery.Entity) ElementKind(javax.lang.model.element.ElementKind) Collection(java.util.Collection) Set(java.util.Set) Element(javax.lang.model.element.Element) IOException(java.io.IOException) GENERATE_ALWAYS(io.requery.processor.EntityProcessor.GENERATE_ALWAYS) Superclass(io.requery.Superclass) Types(javax.lang.model.util.Types) Collectors(java.util.stream.Collectors) TypeKind(javax.lang.model.type.TypeKind) SourceVersion(javax.lang.model.SourceVersion) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) RoundEnvironment(javax.annotation.processing.RoundEnvironment) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Optional(java.util.Optional) Queue(java.util.Queue) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Types(javax.lang.model.util.Types) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) Elements(javax.lang.model.util.Elements) LinkedHashMap(java.util.LinkedHashMap) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) IOException(java.io.IOException) LinkedList(java.util.LinkedList) Collection(java.util.Collection)

Example 4 with RoundEnvironment

use of javax.annotation.processing.RoundEnvironment in project vertx-docgen by vert-x3.

the class BaseProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    for (StackTraceElement elt : trace) {
        if (elt.getClassName().startsWith("org.jetbrains")) {
            return true;
        }
    }
    if (failures.isEmpty()) {
        try {
            if (!roundEnv.processingOver()) {
                roundEnv.getElementsAnnotatedWith(Document.class).forEach(elt -> {
                    try {
                        PackageDoc doc = new PackageDoc((PackageElement) elt);
                        state.put(doc, handleGen(doc));
                    } catch (DocGenException e) {
                        if (e.element == null) {
                            e.element = elt;
                        }
                        throw e;
                    }
                });
                if (sources != null && sources.size() > 0) {
                    for (String source : sources) {
                        // Handle wildcards
                        List<File> files = new ArrayList<>();
                        File f = new File(source);
                        if (!f.exists()) {
                            if (f.getName().contains("*")) {
                                StringBuilder sb = new StringBuilder();
                                for (char c : f.getName().toCharArray()) {
                                    if (c == '*') {
                                        sb.append(".*");
                                    } else {
                                        sb.append(Matcher.quoteReplacement(Character.toString(c)));
                                    }
                                }
                                Pattern p = Pattern.compile(sb.toString());
                                File parentFile = f.getParentFile();
                                File[] children = parentFile.listFiles();
                                if (children != null) {
                                    for (File child : children) {
                                        if (p.matcher(child.getName()).matches()) {
                                            files.add(child);
                                        }
                                    }
                                }
                            } else {
                                throw new FileNotFoundException("Cannot process document " + source);
                            }
                        } else {
                            files.add(f);
                        }
                        for (File file : files) {
                            if (file.isFile()) {
                                FileDoc fileDoc = new FileDoc(file, file.getName());
                                Map<DocGenerator, DocWriter> m = handleGen(fileDoc);
                                state.put(fileDoc, m);
                            } else if (file.isDirectory()) {
                                Files.walk(file.toPath()).map(Path::toFile).filter(File::isFile).forEach(docFile -> {
                                    String relativePath = file.toPath().relativize(docFile.toPath()).toString();
                                    FileDoc fileDoc = new FileDoc(docFile, relativePath);
                                    Map<DocGenerator, DocWriter> m = handleGen(fileDoc);
                                    state.put(fileDoc, m);
                                });
                            } else {
                                throw new IOException("Document " + file.getAbsolutePath() + " is not a file nor a dir");
                            }
                        }
                    }
                    sources.clear();
                }
                Set<String> processed = new HashSet<>();
                while (true) {
                    Optional<ElementResolution> opt = resolutions.values().stream().filter(res -> res.elt == null && !processed.contains(res.signature)).findFirst();
                    if (opt.isPresent()) {
                        ElementResolution res = opt.get();
                        processed.add(res.signature);
                        res.tryResolve();
                    } else {
                        break;
                    }
                }
            } else {
                state.forEach((doc, m) -> {
                    m.forEach((gen, w) -> {
                        String content = postProcess(gen.getName(), w.render());
                        write(gen, doc, content);
                    });
                });
            }
        } catch (Exception e) {
            Element reportedElt = (e instanceof DocGenException) ? ((DocGenException) e).element : null;
            String msg = e.getMessage();
            if (msg == null) {
                msg = e.toString();
            }
            e.printStackTrace();
            if (reportedElt != null) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, reportedElt);
                if (reportedElt instanceof PackageElement) {
                    failures.put(((PackageElement) reportedElt).getQualifiedName().toString(), msg);
                } else {
                    throw new UnsupportedOperationException("not implemented");
                }
            } else {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg);
            }
        }
    }
    return false;
}
Also used : TreePath(com.sun.source.util.TreePath) java.util(java.util) AbstractProcessor(javax.annotation.processing.AbstractProcessor) Files(java.nio.file.Files) URL(java.net.URL) LiteralTree(com.sun.source.doctree.LiteralTree) ErroneousTree(com.sun.source.doctree.ErroneousTree) StandardCharsets(java.nio.charset.StandardCharsets) JavaFileObject(javax.tools.JavaFileObject) SourceVersion(javax.lang.model.SourceVersion) Matcher(java.util.regex.Matcher) java.io(java.io) RoundEnvironment(javax.annotation.processing.RoundEnvironment) Diagnostic(javax.tools.Diagnostic) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) DocTreeScanner(com.sun.source.util.DocTreeScanner) Pattern(java.util.regex.Pattern) javax.lang.model.element(javax.lang.model.element) Path(java.nio.file.Path) com.sun.source.doctree(com.sun.source.doctree) DocTrees(com.sun.source.util.DocTrees) Pattern(java.util.regex.Pattern)

Example 5 with RoundEnvironment

use of javax.annotation.processing.RoundEnvironment in project auto by google.

the class AutoValueCompilationTest method testTypeParametersWithAnnotationsOnBounds.

// Tests that type annotations are correctly copied from the bounds of type parameters in the
// @AutoValue class to the bounds of the corresponding parameters in the generated class. For
// example, if we have `@AutoValue abstract class Foo<T extends @NullableType Object>`, then the
// generated class should be `class AutoValue_Foo<T extends @NullableType Object> extends Foo<T>`.
// Some buggy versions of javac do not report type annotations correctly in this context.
// AutoValue can't copy them if it can't see them, so we make a special annotation processor to
// detect if we are in the presence of this bug and if so we don't fail.
@Test
public void testTypeParametersWithAnnotationsOnBounds() {
    @SupportedAnnotationTypes("*")
    class CompilerBugProcessor extends AbstractProcessor {

        boolean checkedAnnotationsOnTypeBounds;

        boolean reportsAnnotationsOnTypeBounds;

        @Override
        public SourceVersion getSupportedSourceVersion() {
            return SourceVersion.latestSupported();
        }

        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            if (roundEnv.processingOver()) {
                TypeElement test = processingEnv.getElementUtils().getTypeElement("com.example.Test");
                TypeParameterElement t = test.getTypeParameters().get(0);
                this.checkedAnnotationsOnTypeBounds = true;
                this.reportsAnnotationsOnTypeBounds = !t.getBounds().get(0).getAnnotationMirrors().isEmpty();
            }
            return false;
        }
    }
    CompilerBugProcessor compilerBugProcessor = new CompilerBugProcessor();
    JavaFileObject nullableTypeFileObject = JavaFileObjects.forSourceLines("foo.bar.NullableType", "package foo.bar;", "", "import java.lang.annotation.ElementType;", "import java.lang.annotation.Target;", "", "@Target(ElementType.TYPE_USE)", "public @interface NullableType {}");
    JavaFileObject autoValueFileObject = JavaFileObjects.forSourceLines("com.example.Test", "package com.example;", "", "import com.google.auto.value.AutoValue;", "import foo.bar.NullableType;", "", "@AutoValue", "abstract class Test<T extends @NullableType Object & @NullableType Cloneable> {}");
    Compilation compilation = javac().withProcessors(new AutoValueProcessor(), compilerBugProcessor).withOptions("-Xlint:-processing", "-implicit:none").compile(nullableTypeFileObject, autoValueFileObject);
    assertThat(compilation).succeededWithoutWarnings();
    assertThat(compilerBugProcessor.checkedAnnotationsOnTypeBounds).isTrue();
    if (compilerBugProcessor.reportsAnnotationsOnTypeBounds) {
        assertThat(compilation).generatedSourceFile("com.example.AutoValue_Test").contentsAsUtf8String().contains("class AutoValue_Test<T extends @NullableType Object & @NullableType Cloneable>" + " extends Test<T> {");
    }
}
Also used : RoundEnvironment(javax.annotation.processing.RoundEnvironment) JavaFileObject(javax.tools.JavaFileObject) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Compilation(com.google.testing.compile.Compilation) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) TypeElement(javax.lang.model.element.TypeElement) AbstractProcessor(javax.annotation.processing.AbstractProcessor) TypeParameterElement(javax.lang.model.element.TypeParameterElement) Test(org.junit.Test)

Aggregations

RoundEnvironment (javax.annotation.processing.RoundEnvironment)10 AbstractProcessor (javax.annotation.processing.AbstractProcessor)9 TypeElement (javax.lang.model.element.TypeElement)9 Set (java.util.Set)7 SourceVersion (javax.lang.model.SourceVersion)6 JavaFileObject (javax.tools.JavaFileObject)6 IOException (java.io.IOException)5 ProcessingEnvironment (javax.annotation.processing.ProcessingEnvironment)5 Element (javax.lang.model.element.Element)5 Writer (java.io.Writer)4 List (java.util.List)4 Map (java.util.Map)4 SupportedAnnotationTypes (javax.annotation.processing.SupportedAnnotationTypes)4 Diagnostic (javax.tools.Diagnostic)4 ElementKind (javax.lang.model.element.ElementKind)3 TypeMirror (javax.lang.model.type.TypeMirror)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 Arrays (java.util.Arrays)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2