Search in sources :

Example 1 with AbstractBeanDefinitionBuilder

use of io.micronaut.inject.writer.AbstractBeanDefinitionBuilder in project micronaut-core by micronaut-projects.

the class TypeElementVisitorProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    if (!loadedVisitors.isEmpty() && !(annotations.size() == 1 && Generated.class.getName().equals(annotations.iterator().next().getQualifiedName().toString()))) {
        TypeElement groovyObjectTypeElement = elementUtils.getTypeElement("groovy.lang.GroovyObject");
        TypeMirror groovyObjectType = groovyObjectTypeElement != null ? groovyObjectTypeElement.asType() : null;
        Set<TypeElement> elements = new LinkedHashSet<>();
        for (TypeElement annotation : annotations) {
            final Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
            includeElements(elements, annotatedElements, groovyObjectType);
        }
        // This call to getRootElements() should be removed in Micronaut 4. It should not be possible
        // to process elements without at least one annotation present and this call breaks that assumption.
        final Set<? extends Element> rootElements = roundEnv.getRootElements();
        includeElements(elements, rootElements, groovyObjectType);
        if (!elements.isEmpty()) {
            for (LoadedVisitor loadedVisitor : loadedVisitors) {
                for (TypeElement typeElement : elements) {
                    if (!loadedVisitor.matches(typeElement)) {
                        continue;
                    }
                    String className = typeElement.getQualifiedName().toString();
                    typeElement.accept(new ElementVisitor(typeElement, Collections.singletonList(loadedVisitor)), className);
                }
            }
        }
        for (LoadedVisitor loadedVisitor : loadedVisitors) {
            try {
                loadedVisitor.getVisitor().finish(javaVisitorContext);
            } catch (Throwable e) {
                error("Error finalizing type visitor [%s]: %s", loadedVisitor.getVisitor(), e.getMessage());
            }
        }
    }
    final List<AbstractBeanDefinitionBuilder> beanDefinitionBuilders = javaVisitorContext.getBeanElementBuilders();
    if (CollectionUtils.isNotEmpty(beanDefinitionBuilders)) {
        try {
            AbstractBeanDefinitionBuilder.writeBeanDefinitionBuilders(classWriterOutputVisitor, beanDefinitionBuilders);
        } catch (IOException e) {
            // raise a compile error
            String message = e.getMessage();
            error("Unexpected error: %s", message != null ? message : e.getClass().getSimpleName());
        }
    }
    if (roundEnv.processingOver()) {
        javaVisitorContext.finish();
        writeBeanDefinitionsToMetaInf();
    }
    return false;
}
Also used : Generated(io.micronaut.core.annotation.Generated) TypeElement(javax.lang.model.element.TypeElement) TypeElementVisitor(io.micronaut.inject.visitor.TypeElementVisitor) AbstractBeanDefinitionBuilder(io.micronaut.inject.writer.AbstractBeanDefinitionBuilder) IOException(java.io.IOException) LoadedVisitor(io.micronaut.annotation.processing.visitor.LoadedVisitor) TypeMirror(javax.lang.model.type.TypeMirror)

Example 2 with AbstractBeanDefinitionBuilder

use of io.micronaut.inject.writer.AbstractBeanDefinitionBuilder in project micronaut-core by micronaut-projects.

the class BeanDefinitionInjectProcessor method process.

@Override
public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    processingOver = roundEnv.processingOver();
    if (!processingOver) {
        annotations = annotations.stream().filter(ann -> {
            final String name = ann.getQualifiedName().toString();
            String packageName = NameUtils.getPackageName(name);
            return !name.equals(AnnotationUtil.KOTLIN_METADATA) && !AnnotationUtil.STEREOTYPE_EXCLUDES.contains(packageName);
        }).filter(ann -> annotationUtils.hasStereotype(ann, ANNOTATION_STEREOTYPES) || isProcessedAnnotation(ann.getQualifiedName().toString())).collect(Collectors.toSet());
        if (!annotations.isEmpty()) {
            TypeElement groovyObjectTypeElement = elementUtils.getTypeElement("groovy.lang.GroovyObject");
            TypeMirror groovyObjectType = groovyObjectTypeElement != null ? groovyObjectTypeElement.asType() : null;
            // accumulate all the class elements for all annotated elements
            annotations.forEach(annotation -> roundEnv.getElementsAnnotatedWith(annotation).stream().filter(element -> element.getKind() != ANNOTATION_TYPE).forEach(element -> {
                TypeElement typeElement = modelUtils.classElementFor(element);
                if (typeElement == null) {
                    return;
                }
                if (element.getKind() == ENUM) {
                    final AnnotationMetadata am = annotationUtils.getAnnotationMetadata(element);
                    if (isDeclaredBeanInMetadata(am)) {
                        error(element, "Enum types cannot be defined as beans");
                    }
                    return;
                }
                // skip Groovy code, handled by InjectTransform. Required for GroovyEclipse compiler
                if ((groovyObjectType != null && typeUtils.isAssignable(typeElement.asType(), groovyObjectType))) {
                    return;
                }
                String name = typeElement.getQualifiedName().toString();
                if (!beanDefinitions.contains(name) && !processed.contains(name) && !name.endsWith(BeanDefinitionVisitor.PROXY_SUFFIX)) {
                    boolean isInterface = JavaModelUtils.resolveKind(typeElement, ElementKind.INTERFACE).isPresent();
                    if (!isInterface) {
                        beanDefinitions.add(name);
                    } else {
                        if (annotationUtils.hasStereotype(typeElement, INTRODUCTION_TYPE) || annotationUtils.hasStereotype(typeElement, ConfigurationReader.class)) {
                            beanDefinitions.add(name);
                        }
                    }
                }
            }));
        }
        // remove already processed in previous round
        for (String name : processed) {
            beanDefinitions.remove(name);
        }
        // process remaining
        int count = beanDefinitions.size();
        if (count > 0) {
            note("Creating bean classes for %s type elements", count);
            beanDefinitions.forEach(className -> {
                if (processed.add(className)) {
                    final TypeElement refreshedClassElement = elementUtils.getTypeElement(className);
                    try {
                        final AnnBeanElementVisitor visitor = new AnnBeanElementVisitor(refreshedClassElement);
                        refreshedClassElement.accept(visitor, className);
                        visitor.getBeanDefinitionWriters().forEach((name, writer) -> {
                            String beanDefinitionName = writer.getBeanDefinitionName();
                            if (processed.add(beanDefinitionName)) {
                                processBeanDefinitions(writer);
                            }
                        });
                        AnnotationUtils.invalidateMetadata(refreshedClassElement);
                    } catch (PostponeToNextRoundException e) {
                        processed.remove(className);
                    }
                }
            });
            AnnotationUtils.invalidateCache();
        }
    }
    /*
        Since the underlying Filer expects us to write only once into a file we need to make sure it happens in the last
        processing round.
        */
    if (processingOver) {
        try {
            writeBeanDefinitionsToMetaInf();
            for (BeanElementVisitor<?> visitor : BeanElementVisitor.VISITORS) {
                if (visitor.isEnabled()) {
                    try {
                        visitor.finish(javaVisitorContext);
                    } catch (Exception e) {
                        javaVisitorContext.fail("Error finalizing bean element visitor [" + visitor.getClass().getName() + "]: " + e.getMessage(), null);
                    }
                }
            }
            final List<AbstractBeanDefinitionBuilder> beanElementBuilders = javaVisitorContext.getBeanElementBuilders();
            if (CollectionUtils.isNotEmpty(beanElementBuilders)) {
                try {
                    AbstractBeanDefinitionBuilder.writeBeanDefinitionBuilders(classWriterOutputVisitor, beanElementBuilders);
                } catch (IOException e) {
                    // raise a compile error
                    String message = e.getMessage();
                    error("Unexpected error: %s", message != null ? message : e.getClass().getSimpleName());
                }
            }
        } finally {
            AnnotationUtils.invalidateCache();
            AbstractAnnotationMetadataBuilder.clearMutated();
            JavaAnnotationMetadataBuilder.clearCaches();
        }
    }
    return false;
}
Also used : InterceptorBinding(io.micronaut.aop.InterceptorBinding) Bindable(io.micronaut.core.bind.annotation.Bindable) Arrays(java.util.Arrays) SupportedOptions(javax.annotation.processing.SupportedOptions) Modifier(javax.lang.model.element.Modifier) TypeElement(javax.lang.model.element.TypeElement) Internal(io.micronaut.core.annotation.Internal) Introduction(io.micronaut.aop.Introduction) Duration(java.time.Duration) Map(java.util.Map) PropertyMetadata(io.micronaut.inject.configuration.PropertyMetadata) AnnotationClassValue(io.micronaut.core.annotation.AnnotationClassValue) Property(io.micronaut.context.annotation.Property) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) Set(java.util.Set) Element(javax.lang.model.element.Element) Bean(io.micronaut.context.annotation.Bean) Interceptor(io.micronaut.aop.Interceptor) MethodElement(io.micronaut.inject.ast.MethodElement) AnnotationValue(javax.lang.model.element.AnnotationValue) EachProperty(io.micronaut.context.annotation.EachProperty) RequiresCondition(io.micronaut.context.RequiresCondition) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) ConfigurationMetadata(io.micronaut.inject.configuration.ConfigurationMetadata) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) LinkedHashMap(java.util.LinkedHashMap) TypedElement(io.micronaut.inject.ast.TypedElement) Nullable(io.micronaut.core.annotation.Nullable) DeclaredType(javax.lang.model.type.DeclaredType) ElementFilter(javax.lang.model.util.ElementFilter) LinkedHashSet(java.util.LinkedHashSet) InterceptedMethodUtil(io.micronaut.aop.internal.intercepted.InterceptedMethodUtil) IOException(java.io.IOException) OptionalValues(io.micronaut.core.value.OptionalValues) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CONSTRUCTOR(javax.lang.model.element.ElementKind.CONSTRUCTOR) RoundEnvironment(javax.annotation.processing.RoundEnvironment) ElementQuery(io.micronaut.inject.ast.ElementQuery) BeanElementVisitor(io.micronaut.inject.visitor.BeanElementVisitor) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) ConfigurationInject(io.micronaut.context.annotation.ConfigurationInject) ENUM(javax.lang.model.element.ElementKind.ENUM) DefaultScope(io.micronaut.context.annotation.DefaultScope) JavaVisitorContext(io.micronaut.annotation.processing.visitor.JavaVisitorContext) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConfigurationBuilder(io.micronaut.context.annotation.ConfigurationBuilder) NameUtils(io.micronaut.core.naming.NameUtils) JavaMethodElement(io.micronaut.annotation.processing.visitor.JavaMethodElement) Executable(io.micronaut.context.annotation.Executable) Context(io.micronaut.context.annotation.Context) Predicate(java.util.function.Predicate) AccessorsStyle(io.micronaut.core.annotation.AccessorsStyle) Collectors(java.util.stream.Collectors) TypeKind(javax.lang.model.type.TypeKind) Objects(java.util.Objects) StringUtils(io.micronaut.core.util.StringUtils) ElementScanner8(javax.lang.model.util.ElementScanner8) List(java.util.List) Factory(io.micronaut.context.annotation.Factory) AnnotationUtil(io.micronaut.core.annotation.AnnotationUtil) JavaElementFactory(io.micronaut.annotation.processing.visitor.JavaElementFactory) TypeVariable(javax.lang.model.type.TypeVariable) Optional(java.util.Optional) AbstractBeanDefinitionBuilder(io.micronaut.inject.writer.AbstractBeanDefinitionBuilder) BeanDefinitionWriter(io.micronaut.inject.writer.BeanDefinitionWriter) OriginatingElements(io.micronaut.inject.writer.OriginatingElements) ClassElement(io.micronaut.inject.ast.ClassElement) Adapter(io.micronaut.aop.Adapter) HashSet(java.util.HashSet) ANNOTATION_TYPE(javax.lang.model.element.ElementKind.ANNOTATION_TYPE) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) Requires(io.micronaut.context.annotation.Requires) ConfigurationReader(io.micronaut.context.annotation.ConfigurationReader) AbstractAnnotationMetadataBuilder(io.micronaut.inject.annotation.AbstractAnnotationMetadataBuilder) Name(javax.lang.model.element.Name) BeanDefinitionReferenceWriter(io.micronaut.inject.writer.BeanDefinitionReferenceWriter) VisitorConfiguration(io.micronaut.inject.visitor.VisitorConfiguration) ElementKind(javax.lang.model.element.ElementKind) ExecutableElement(javax.lang.model.element.ExecutableElement) FIELD(javax.lang.model.element.ElementKind.FIELD) Value(io.micronaut.context.annotation.Value) TypeParameterElement(javax.lang.model.element.TypeParameterElement) InterceptorKind(io.micronaut.aop.InterceptorKind) TimeUnit(java.util.concurrent.TimeUnit) NonNull(io.micronaut.core.annotation.NonNull) TypeMirror(javax.lang.model.type.TypeMirror) CollectionUtils(io.micronaut.core.util.CollectionUtils) AopProxyWriter(io.micronaut.aop.writer.AopProxyWriter) ConfigurationMetadataBuilder(io.micronaut.inject.configuration.ConfigurationMetadataBuilder) BeanDefinitionVisitor(io.micronaut.inject.writer.BeanDefinitionVisitor) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) PrimitiveType(javax.lang.model.type.PrimitiveType) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) TypeElement(javax.lang.model.element.TypeElement) AbstractBeanDefinitionBuilder(io.micronaut.inject.writer.AbstractBeanDefinitionBuilder) IOException(java.io.IOException) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) IOException(java.io.IOException) TypeMirror(javax.lang.model.type.TypeMirror)

Aggregations

AbstractBeanDefinitionBuilder (io.micronaut.inject.writer.AbstractBeanDefinitionBuilder)2 IOException (java.io.IOException)2 TypeElement (javax.lang.model.element.TypeElement)2 TypeMirror (javax.lang.model.type.TypeMirror)2 JavaElementFactory (io.micronaut.annotation.processing.visitor.JavaElementFactory)1 JavaMethodElement (io.micronaut.annotation.processing.visitor.JavaMethodElement)1 JavaVisitorContext (io.micronaut.annotation.processing.visitor.JavaVisitorContext)1 LoadedVisitor (io.micronaut.annotation.processing.visitor.LoadedVisitor)1 Adapter (io.micronaut.aop.Adapter)1 Interceptor (io.micronaut.aop.Interceptor)1 InterceptorBinding (io.micronaut.aop.InterceptorBinding)1 InterceptorKind (io.micronaut.aop.InterceptorKind)1 Introduction (io.micronaut.aop.Introduction)1 InterceptedMethodUtil (io.micronaut.aop.internal.intercepted.InterceptedMethodUtil)1 AopProxyWriter (io.micronaut.aop.writer.AopProxyWriter)1 RequiresCondition (io.micronaut.context.RequiresCondition)1 Bean (io.micronaut.context.annotation.Bean)1 ConfigurationBuilder (io.micronaut.context.annotation.ConfigurationBuilder)1 ConfigurationInject (io.micronaut.context.annotation.ConfigurationInject)1 ConfigurationReader (io.micronaut.context.annotation.ConfigurationReader)1