Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip classes from introspection generation that are postponed #11155

Merged
merged 5 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.micronaut.inject.ast.MethodElement;
import io.micronaut.inject.ast.PropertyElement;
import io.micronaut.inject.ast.PropertyElementQuery;
import io.micronaut.inject.visitor.ElementPostponedToNextRoundException;
import io.micronaut.inject.visitor.TypeElementVisitor;
import io.micronaut.inject.visitor.VisitorContext;
import io.micronaut.inject.writer.ClassGenerationException;
Expand Down Expand Up @@ -256,13 +257,16 @@ public VisitorKind getVisitorKind() {
public void finish(VisitorContext visitorContext) {
try {
if (!writers.isEmpty()) {
for (BeanIntrospectionWriter writer : writers.values()) {
writers.forEach((className, writer) -> {
try {
writer.accept(visitorContext);
} catch (ElementPostponedToNextRoundException ignore) {
// Ignore, next round will redo
} catch (IOException e) {
throw new ClassGenerationException("I/O error occurred during class generation: " + e.getMessage(), e);
}
}
});

}
} finally {
writers.clear();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.inject.visitor;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.inject.ast.Element;

/**
* Exception is thrown when the visitor is attempted to create a new file but the originated element is postponed to the next round.
*
* @author Denis Stepanov
* @since 4.7
*/
@Internal
public final class ElementPostponedToNextRoundException extends RuntimeException {

private final Element originatingElement;

/**
* @param originatingElement The originating element
*/
public ElementPostponedToNextRoundException(@NonNull Element originatingElement) {
super("Original element: " + originatingElement.getName() + " is postponed to the next round!");
this.originatingElement = originatingElement;
}

@NonNull
public Element getOriginatingElement() {
return originatingElement;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -77,6 +78,7 @@ abstract class AbstractInjectAnnotationProcessor extends AbstractProcessor {
private final Set<String> supportedAnnotationTypes = new HashSet<>(5);
private final Map<String, Boolean> isProcessedCache = new HashMap<>(30);
private Set<String> processedTypes;
protected Set<String> postponedTypes = new LinkedHashSet<>();

@Override
public SourceVersion getSupportedSourceVersion() {
Expand Down Expand Up @@ -216,7 +218,8 @@ protected JavaVisitorContext newVisitorContext(@NonNull ProcessingEnvironment pr
modelUtils,
filer,
visitorAttributes,
getVisitorKind()
getVisitorKind(),
postponedTypes
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.Set;

/**
* Utility methods for annotations.
Expand Down Expand Up @@ -143,7 +144,8 @@ public JavaVisitorContext newVisitorContext() {
modelUtils,
filer,
visitorAttributes,
TypeElementVisitor.VisitorKind.ISOLATING
TypeElementVisitor.VisitorKind.ISOLATING,
Set.of()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ public class TypeElementVisitorProcessor extends AbstractInjectAnnotationProcess

private List<LoadedVisitor> loadedVisitors;
private Collection<? extends TypeElementVisitor<?, ?>> typeElementVisitors;
private final Set<String> pendingTypes = new LinkedHashSet<>();

/**
* The visited annotation names.
Expand Down Expand Up @@ -241,8 +240,8 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
roundEnv.getRootElements()
).filter(notGroovyObject).forEach(elements::add);

pendingTypes.stream().map(elementUtils::getTypeElement).filter(Objects::nonNull).forEach(elements::add);
pendingTypes.clear();
postponedTypes.stream().map(elementUtils::getTypeElement).filter(Objects::nonNull).forEach(elements::add);
postponedTypes.clear();

if (!elements.isEmpty()) {

Expand Down Expand Up @@ -272,7 +271,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
}
error(originatingElement.element(), e.getMessage());
} catch (PostponeToNextRoundException e) {
pendingTypes.add(javaClassElement.getName());
postponedTypes.add(javaClassElement.getName());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import java.lang.annotation.Annotation;
Expand Down Expand Up @@ -265,11 +266,15 @@ public boolean isPrimitive() {
@Override
public Collection<ClassElement> getInterfaces() {
if (resolvedInterfaces == null) {
resolvedInterfaces = classElement.getInterfaces().stream().map(mirror -> newClassElement(mirror, getTypeArguments())).toList();
resolvedInterfaces = classElement.getInterfaces().stream().filter(this::onlyAvailable).map(mirror -> newClassElement(mirror, getTypeArguments())).toList();
}
return resolvedInterfaces;
}

private boolean onlyAvailable(TypeMirror mirror) {
return !(mirror instanceof DeclaredType declaredType) || declaredType.getKind() != TypeKind.ERROR;
}

@Override
public Optional<ClassElement> getSuperType() {
if (resolvedSuperType == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import io.micronaut.annotation.processing.AnnotationProcessingOutputVisitor;
import io.micronaut.annotation.processing.AnnotationUtils;
import io.micronaut.inject.visitor.ElementPostponedToNextRoundException;
import io.micronaut.annotation.processing.GenericUtils;
import io.micronaut.annotation.processing.JavaAnnotationMetadataBuilder;
import io.micronaut.annotation.processing.JavaElementAnnotationMetadataFactory;
Expand Down Expand Up @@ -66,6 +67,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -100,6 +102,7 @@ public final class JavaVisitorContext implements VisitorContext, BeanElementVisi
private final JavaElementAnnotationMetadataFactory elementAnnotationMetadataFactory;
private final JavaNativeElementsHelper nativeElementsHelper;
private final Filer filer;
private final Set<String> postponedTypes;

/**
* The default constructor.
Expand Down Expand Up @@ -128,7 +131,7 @@ public JavaVisitorContext(
Filer filer,
MutableConvertibleValues<Object> visitorAttributes,
TypeElementVisitor.VisitorKind visitorKind) {
this(processingEnv, messager, elements, types, modelUtils, filer, visitorAttributes, visitorKind);
this(processingEnv, messager, elements, types, modelUtils, filer, visitorAttributes, visitorKind, new HashSet<>());
}

/**
Expand All @@ -142,7 +145,9 @@ public JavaVisitorContext(
* @param filer The filer
* @param visitorAttributes The attributes
* @param visitorKind The visitor kind
* @deprecated No longer needed
*/
@Deprecated(forRemoval = true, since = "4.7.0")
public JavaVisitorContext(
ProcessingEnvironment processingEnv,
Messager messager,
Expand All @@ -152,6 +157,32 @@ public JavaVisitorContext(
Filer filer,
MutableConvertibleValues<Object> visitorAttributes,
TypeElementVisitor.VisitorKind visitorKind) {
this(processingEnv, messager, elements, types, modelUtils, filer, visitorAttributes, visitorKind, Set.of());
}

/**
* The default constructor.
*
* @param processingEnv The processing environment
* @param messager The messager
* @param elements The elements
* @param types Type types
* @param modelUtils The model utils
* @param filer The filer
* @param visitorAttributes The attributes
* @param visitorKind The visitor kind
* @param postponedTypes The postponed types
*/
public JavaVisitorContext(
ProcessingEnvironment processingEnv,
Messager messager,
Elements elements,
Types types,
ModelUtils modelUtils,
Filer filer,
MutableConvertibleValues<Object> visitorAttributes,
TypeElementVisitor.VisitorKind visitorKind,
Set<String> postponedTypes) {
this.messager = messager;
this.elements = elements;
this.types = types;
Expand All @@ -166,6 +197,7 @@ public JavaVisitorContext(
this.elementAnnotationMetadataFactory = new JavaElementAnnotationMetadataFactory(false, this.annotationMetadataBuilder);
this.expressionCompilationContextFactory = new DefaultExpressionCompilationContextFactory(this);
this.filer = filer;
this.postponedTypes = postponedTypes;
}

@Override
Expand Down Expand Up @@ -321,13 +353,29 @@ private void printMessage(String message, Diagnostic.Kind kind, @Nullable io.mic
}
}

private void checkForPostponedOriginalElement(io.micronaut.inject.ast.Element originatingElement) {
if (originatingElement != null && postponedTypes.contains(originatingElement.getName())) {
throw new ElementPostponedToNextRoundException(originatingElement);
}
}

private void checkForPostponedOriginalElements(io.micronaut.inject.ast.Element[] originatingElements) {
if (originatingElements != null) {
for (io.micronaut.inject.ast.Element originatingElement : originatingElements) {
checkForPostponedOriginalElement(originatingElement);
}
}
}

@Override
public OutputStream visitClass(String classname, @Nullable io.micronaut.inject.ast.Element originatingElement) throws IOException {
checkForPostponedOriginalElement(originatingElement);
return outputVisitor.visitClass(classname, new io.micronaut.inject.ast.Element[] {originatingElement});
}

@Override
public OutputStream visitClass(String classname, io.micronaut.inject.ast.Element... originatingElements) throws IOException {
checkForPostponedOriginalElements(originatingElements);
return outputVisitor.visitClass(classname, originatingElements);
}

Expand All @@ -338,11 +386,13 @@ public void visitServiceDescriptor(String type, String classname) {

@Override
public void visitServiceDescriptor(String type, String classname, io.micronaut.inject.ast.Element originatingElement) {
checkForPostponedOriginalElement(originatingElement);
outputVisitor.visitServiceDescriptor(type, classname, originatingElement);
}

@Override
public Optional<GeneratedFile> visitMetaInfFile(String path, io.micronaut.inject.ast.Element... originatingElements) {
checkForPostponedOriginalElements(originatingElements);
return outputVisitor.visitMetaInfFile(path, originatingElements);
}

Expand All @@ -353,11 +403,13 @@ public Optional<GeneratedFile> visitGeneratedFile(String path) {

@Override
public Optional<GeneratedFile> visitGeneratedFile(String path, io.micronaut.inject.ast.Element... originatingElements) {
checkForPostponedOriginalElements(originatingElements);
return outputVisitor.visitGeneratedFile(path, originatingElements);
}

@Override
public Optional<GeneratedFile> visitGeneratedSourceFile(String packageName, String fileNameWithoutExtension, io.micronaut.inject.ast.Element... originatingElements) {
checkForPostponedOriginalElements(originatingElements);
return outputVisitor.visitGeneratedSourceFile(packageName, fileNameWithoutExtension, originatingElements);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.micronaut.visitors


import io.micronaut.annotation.processing.test.AbstractTypeElementSpec

class PostponedVisitorsSpec extends AbstractTypeElementSpec {

void 'test'() {
when:
def definition = buildBeanIntrospection('test.Walrus', '''
package test;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.visitors.Wither;

@Introspected
@Wither
public record Walrus (
@NonNull
String name,
int age,
byte[] chipInfo
) implements WalrusWither {
}

''')
then:
definition
}
}
8 changes: 8 additions & 0 deletions inject-java/src/test/groovy/io/micronaut/visitors/Wither.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.micronaut.visitors;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Wither {
}
Loading
Loading