Skip to content

Commit 889d91c

Browse files
committed
Overhaul annotation support for code generation
This commit improves the annotation support so that it handles more attribute types. An AnnotationContainer is introduced that permits to further configure an annotation. This commit adds a number of deprecations: * Annotation#getName has been deprecated in favor of Annotation#getClasName. * Annotable#annotate has been deprecated in favor of Annotable#annotations()#add. * Annotable#getAnnotations has been deprecated in favor of Annotable#annotations()#values. * Annotation#name has been deprecated in favor of Annotation#of. This commit also introduces a breaking change by removing the attribute method on Annotation.Builder as specifying the type of the attribute is now handled automatically. Use Annotation.Builder#add or Annotation.Builder#set depending on your needs. Closes spring-iogh-1424
1 parent 1d9e6b5 commit 889d91c

24 files changed

+1202
-441
lines changed

initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/SourceCodeProjectGenerationConfiguration.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
2020
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
21-
import io.spring.initializr.generator.language.Annotation;
21+
import io.spring.initializr.generator.language.ClassName;
2222
import io.spring.initializr.generator.language.TypeDeclaration;
2323
import io.spring.initializr.generator.packaging.war.WarPackaging;
2424
import io.spring.initializr.generator.project.ProjectDescription;
@@ -38,14 +38,14 @@ public class SourceCodeProjectGenerationConfiguration {
3838

3939
@Bean
4040
public MainApplicationTypeCustomizer<TypeDeclaration> springBootApplicationAnnotator() {
41-
return (typeDeclaration) -> typeDeclaration
42-
.annotate(Annotation.name("org.springframework.boot.autoconfigure.SpringBootApplication"));
41+
return (typeDeclaration) -> typeDeclaration.annotations()
42+
.add(ClassName.of("org.springframework.boot.autoconfigure.SpringBootApplication"));
4343
}
4444

4545
@Bean
4646
public TestApplicationTypeCustomizer<TypeDeclaration> junitJupiterSpringBootTestTypeCustomizer() {
47-
return (typeDeclaration) -> typeDeclaration
48-
.annotate(Annotation.name("org.springframework.boot.test.context.SpringBootTest"));
47+
return (typeDeclaration) -> typeDeclaration.annotations()
48+
.add(ClassName.of("org.springframework.boot.test.context.SpringBootTest"));
4949
}
5050

5151
/**

initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/groovy/GroovyProjectGenerationDefaultContributorsConfiguration.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
2323
import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
2424
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
25-
import io.spring.initializr.generator.language.Annotation;
25+
import io.spring.initializr.generator.language.ClassName;
2626
import io.spring.initializr.generator.language.CodeBlock;
2727
import io.spring.initializr.generator.language.Parameter;
2828
import io.spring.initializr.generator.language.groovy.GroovyMethodDeclaration;
@@ -66,7 +66,7 @@ TestApplicationTypeCustomizer<GroovyTypeDeclaration> junitJupiterTestMethodContr
6666
GroovyMethodDeclaration method = GroovyMethodDeclaration.method("contextLoads")
6767
.returning("void")
6868
.body(CodeBlock.of(""));
69-
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
69+
method.annotations().add(ClassName.of("org.junit.jupiter.api.Test"));
7070
typeDeclaration.addMethodDeclaration(method);
7171
};
7272
}
@@ -93,7 +93,7 @@ ServletInitializerCustomizer<GroovyTypeDeclaration> javaServletInitializerCustom
9393
.parameters(
9494
new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application"))
9595
.body(CodeBlock.ofStatement("application.sources($L)", description.getApplicationName()));
96-
configure.annotate(Annotation.name("java.lang.Override"));
96+
configure.annotations().add(ClassName.of(Override.class));
9797
typeDeclaration.addMethodDeclaration(configure);
9898
};
9999
}

initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/java/JavaProjectGenerationDefaultContributorsConfiguration.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.lang.reflect.Modifier;
2020

2121
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
22-
import io.spring.initializr.generator.language.Annotation;
22+
import io.spring.initializr.generator.language.ClassName;
2323
import io.spring.initializr.generator.language.CodeBlock;
2424
import io.spring.initializr.generator.language.Parameter;
2525
import io.spring.initializr.generator.language.java.JavaMethodDeclaration;
@@ -61,7 +61,7 @@ TestApplicationTypeCustomizer<JavaTypeDeclaration> junitJupiterTestMethodContrib
6161
JavaMethodDeclaration method = JavaMethodDeclaration.method("contextLoads")
6262
.returning("void")
6363
.body(CodeBlock.of(""));
64-
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
64+
method.annotations().add(ClassName.of("org.junit.jupiter.api.Test"));
6565
typeDeclaration.addMethodDeclaration(method);
6666
};
6767
}
@@ -85,7 +85,7 @@ ServletInitializerCustomizer<JavaTypeDeclaration> javaServletInitializerCustomiz
8585
new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application"))
8686
.body(CodeBlock.ofStatement("return application.sources($L.class)",
8787
description.getApplicationName()));
88-
configure.annotate(Annotation.name("java.lang.Override"));
88+
configure.annotations().add(ClassName.of(Override.class));
8989
typeDeclaration.addMethodDeclaration(configure);
9090
};
9191
}

initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
2323
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
2424
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
25-
import io.spring.initializr.generator.language.Annotation;
25+
import io.spring.initializr.generator.language.ClassName;
2626
import io.spring.initializr.generator.language.CodeBlock;
2727
import io.spring.initializr.generator.language.Parameter;
2828
import io.spring.initializr.generator.language.kotlin.KotlinCompilationUnit;
@@ -55,7 +55,7 @@ TestApplicationTypeCustomizer<KotlinTypeDeclaration> junitJupiterTestMethodContr
5555
return (typeDeclaration) -> {
5656
KotlinFunctionDeclaration function = KotlinFunctionDeclaration.function("contextLoads")
5757
.body(CodeBlock.of(""));
58-
function.annotate(Annotation.name("org.junit.jupiter.api.Test"));
58+
function.annotations().add(ClassName.of("org.junit.jupiter.api.Test"));
5959
typeDeclaration.addFunctionDeclaration(function);
6060
};
6161
}

initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/SourceCodeProjectGenerationConfigurationTests.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.spring.initializr.generator.spring.code;
1818

19+
import io.spring.initializr.generator.language.ClassName;
1920
import io.spring.initializr.generator.language.CompilationUnit;
2021
import io.spring.initializr.generator.language.SourceCode;
2122
import io.spring.initializr.generator.language.TypeDeclaration;
@@ -50,18 +51,17 @@ void addsACustomizerThatAppliesSpringBootApplicationAnnotationOnMainClass() {
5051
bean.customize(type);
5152
return type;
5253
});
53-
assertThat(declaration.getAnnotations()).hasSize(1);
54-
assertThat(declaration.getAnnotations()).singleElement()
55-
.satisfies((annotation) -> assertThat(annotation.getName())
56-
.isEqualTo("org.springframework.boot.autoconfigure.SpringBootApplication"));
54+
assertThat(declaration.annotations().values()).singleElement()
55+
.satisfies((annotation) -> assertThat(annotation.getClassName())
56+
.isEqualTo(ClassName.of("org.springframework.boot.autoconfigure.SpringBootApplication")));
5757
}
5858

5959
@Test
6060
void addsACustomizerThatAppliesTestAnnotationsOnTestClassWithJunit5() {
6161
TypeDeclaration declaration = generateTestTypeDeclaration("2.2.0.RELEASE");
62-
assertThat(declaration.getAnnotations()).hasSize(1);
63-
assertThat(declaration.getAnnotations().get(0).getName())
64-
.isEqualTo("org.springframework.boot.test.context.SpringBootTest");
62+
assertThat(declaration.annotations().values()).singleElement()
63+
.satisfies((annotation) -> assertThat(annotation.getClassName())
64+
.isEqualTo(ClassName.of("org.springframework.boot.test.context.SpringBootTest")));
6565
}
6666

6767
@SuppressWarnings("unchecked")

initializr-generator/src/main/java/io/spring/initializr/generator/language/Annotatable.java

+27-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,11 +22,35 @@
2222
* A representation of something that can be annotated.
2323
*
2424
* @author Andy Wilkinson
25+
* @author Stephane Nicoll
2526
*/
2627
public interface Annotatable {
2728

28-
void annotate(Annotation annotation);
29+
/**
30+
* Return the {@link AnnotationContainer} to use to configure the annotations of this
31+
* element.
32+
* @return the annotation container
33+
*/
34+
AnnotationContainer annotations();
2935

30-
List<Annotation> getAnnotations();
36+
/**
37+
* Add the specified {@link Annotation}.
38+
* @param annotation the annotation to add
39+
* @deprecated since 0.20.0 in favor of {@link #annotations()}
40+
*/
41+
@Deprecated(since = "0.20.0", forRemoval = true)
42+
default void annotate(Annotation annotation) {
43+
annotations().add(annotation.getClassName(), (builder) -> builder.from(annotation));
44+
}
45+
46+
/**
47+
* Return the configured {@linkplain Annotation annotations}.
48+
* @return the annotations
49+
* @deprecated since 0.20.0 in favor of {@link #annotations()}
50+
*/
51+
@Deprecated(since = "0.20.0", forRemoval = true)
52+
default List<Annotation> getAnnotations() {
53+
return annotations().values().toList();
54+
}
3155

3256
}

0 commit comments

Comments
 (0)