3434public class AddConfigurationAnnotationIfBeansPresent extends Recipe {
3535
3636 private static final String FQN_BEAN = "org.springframework.context.annotation.Bean" ;
37- private static final String CONFIGURATION_PACKAGE = "org.springframework.context.annotation" ;
38- private static final String CONFIGURATION_SIMPLE_NAME = "Configuration" ;
39- private static final String FQN_CONFIGURATION = CONFIGURATION_PACKAGE + "." + CONFIGURATION_SIMPLE_NAME ;
40- private static final AnnotationMatcher BEAN_ANNOTATION_MATCHER = new AnnotationMatcher ("@" + FQN_BEAN , true );
41- private static final AnnotationMatcher CONFIGURATION_ANNOTATION_MATCHER = new AnnotationMatcher ("@" + FQN_CONFIGURATION , true );
37+ private static final String CONFIGURATION_PACKAGE = "org.springframework.context.annotation" ;
38+ private static final String CONFIGURATION_SIMPLE_NAME = "Configuration" ;
39+ private static final String FQN_CONFIGURATION = CONFIGURATION_PACKAGE + "." + CONFIGURATION_SIMPLE_NAME ;
40+ private static final AnnotationMatcher BEAN_ANNOTATION_MATCHER = new AnnotationMatcher ("@" + FQN_BEAN , true );
41+ private static final AnnotationMatcher CONFIGURATION_ANNOTATION_MATCHER = new AnnotationMatcher ("@" + FQN_CONFIGURATION , true );
4242
4343
44- @ Override
44+ @ Override
4545 public String getDisplayName () {
4646 return "Add missing '@Configuration' annotation" ;
4747 }
@@ -59,82 +59,82 @@ protected TreeVisitor<?, ExecutionContext> getApplicableTest() {
5959 @ Override
6060 protected TreeVisitor <?, ExecutionContext > getVisitor () {
6161 return new JavaIsoVisitor <ExecutionContext >() {
62- @ Override
63- public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext p ) {
64- J .ClassDeclaration c = super .visitClassDeclaration (classDecl , p );
65- if (isApplicableClass (c , getCursor ())) {
66- c = addConfigurationAnnotation (c );
67- }
68- return c ;
69- }
70-
71- private J .ClassDeclaration addConfigurationAnnotation (J .ClassDeclaration c ) {
72- maybeAddImport (FQN_CONFIGURATION );
73- JavaTemplate template = JavaTemplate .builder (this ::getCursor , "@" + CONFIGURATION_SIMPLE_NAME )
74- .imports (FQN_CONFIGURATION )
75- .javaParser (() -> JavaParser .fromJavaVersion ().dependsOn ("package " + CONFIGURATION_PACKAGE
76- + "; public @interface " + CONFIGURATION_SIMPLE_NAME + " {}" ).build ())
77- .build ();
78- return c .withTemplate (template ,
79- c .getCoordinates ().addAnnotation (Comparator .comparing (J .Annotation ::getSimpleName )));
80- }
81- };
62+ @ Override
63+ public J .ClassDeclaration visitClassDeclaration (J .ClassDeclaration classDecl , ExecutionContext p ) {
64+ J .ClassDeclaration c = super .visitClassDeclaration (classDecl , p );
65+ if (isApplicableClass (c , getCursor ())) {
66+ c = addConfigurationAnnotation (c );
67+ }
68+ return c ;
69+ }
70+
71+ private J .ClassDeclaration addConfigurationAnnotation (J .ClassDeclaration c ) {
72+ maybeAddImport (FQN_CONFIGURATION );
73+ JavaTemplate template = JavaTemplate .builder (this ::getCursor , "@" + CONFIGURATION_SIMPLE_NAME )
74+ .imports (FQN_CONFIGURATION )
75+ .javaParser (() -> JavaParser .fromJavaVersion ().dependsOn ("package " + CONFIGURATION_PACKAGE
76+ + "; public @interface " + CONFIGURATION_SIMPLE_NAME + " {}" ).build ())
77+ .build ();
78+ return c .withTemplate (template ,
79+ c .getCoordinates ().addAnnotation (Comparator .comparing (J .Annotation ::getSimpleName )));
80+ }
81+ };
82+ }
83+
84+ public static boolean isApplicableClass (J .ClassDeclaration classDecl , Cursor cursor ) {
85+ if (classDecl .getKind () != J .ClassDeclaration .Kind .Type .Class ) {
86+ return false ;
87+ }
88+
89+ boolean isStatic = false ;
90+ for (J .Modifier m : classDecl .getModifiers ()) {
91+ if (m .getType () == J .Modifier .Type .Abstract ) {
92+ return false ;
93+ } else if (m .getType () == J .Modifier .Type .Static ) {
94+ isStatic = true ;
95+ }
96+ }
97+
98+ if (!isStatic ) {
99+ // no static keyword? check if it is top level class in the CU
100+ J .CompilationUnit cu = cursor .dropParentUntil (J .CompilationUnit .class ::isInstance ).getValue ();
101+ if (!cu .getClasses ().contains (classDecl )) {
102+ return false ;
103+ }
104+ }
105+
106+ // check if '@Configuration' is already over the class
107+ for (J .Annotation a : classDecl .getLeadingAnnotations ()) {
108+ JavaType .FullyQualified aType = TypeUtils .asFullyQualified (a .getType ());
109+ if (aType != null && CONFIGURATION_ANNOTATION_MATCHER .matchesAnnotationOrMetaAnnotation (aType )) {
110+ // Found '@Configuration' annotation
111+ return false ;
112+ }
113+ }
114+ // No '@Configuration' present. Check if any methods have '@Bean' annotation
115+ for (Statement s : classDecl .getBody ().getStatements ()) {
116+ if (s instanceof J .MethodDeclaration ) {
117+ if (isBeanMethod ((J .MethodDeclaration ) s )) {
118+ return true ;
119+ }
120+ }
121+ }
122+
123+ return false ;
82124 }
83125
84- public static boolean isApplicableClass (J .ClassDeclaration classDecl , Cursor cursor ) {
85- if (classDecl .getKind () != J .ClassDeclaration .Kind .Type .Class ) {
86- return false ;
87- }
88-
89- boolean isStatic = false ;
90- for (J .Modifier m : classDecl .getModifiers ()) {
91- if (m .getType () == J .Modifier .Type .Abstract ) {
92- return false ;
93- } else if (m .getType () == J .Modifier .Type .Static ) {
94- isStatic = true ;
95- }
96- }
97-
98- if (!isStatic ) {
99- // no static keyword? check if it is top level class in the CU
100- J .CompilationUnit cu = cursor .dropParentUntil (J .CompilationUnit .class ::isInstance ).getValue ();
101- if (!cu .getClasses ().contains (classDecl )) {
102- return false ;
103- }
104- }
105-
106- // check if '@Configuration' is already over the class
107- for (J .Annotation a : classDecl .getLeadingAnnotations ()) {
108- JavaType .FullyQualified aType = TypeUtils .asFullyQualified (a .getType ());
109- if (aType != null && CONFIGURATION_ANNOTATION_MATCHER .matchesAnnotationOrMetaAnnotation (aType )) {
110- // Found '@Configuration' annotation
111- return false ;
112- }
113- }
114- // No '@Configuration' present. Check if any methods have '@Bean' annotation
115- for (Statement s : classDecl .getBody ().getStatements ()) {
116- if (s instanceof J .MethodDeclaration ) {
117- if (isBeanMethod ((J .MethodDeclaration ) s )) {
118- return true ;
119- }
120- }
121- }
122-
123- return false ;
124- }
125-
126- private static boolean isBeanMethod (J .MethodDeclaration methodDecl ) {
127- for (J .Modifier m : methodDecl .getModifiers ()) {
128- if (m .getType () == J .Modifier .Type .Abstract || m .getType () == J .Modifier .Type .Static ) {
129- return false ;
130- }
131- }
132- for (J .Annotation a : methodDecl .getLeadingAnnotations ()) {
133- JavaType .FullyQualified aType = TypeUtils .asFullyQualified (a .getType ());
134- if (aType != null && BEAN_ANNOTATION_MATCHER .matchesAnnotationOrMetaAnnotation (aType )) {
135- return true ;
136- }
137- }
138- return false ;
139- }
126+ private static boolean isBeanMethod (J .MethodDeclaration methodDecl ) {
127+ for (J .Modifier m : methodDecl .getModifiers ()) {
128+ if (m .getType () == J .Modifier .Type .Abstract || m .getType () == J .Modifier .Type .Static ) {
129+ return false ;
130+ }
131+ }
132+ for (J .Annotation a : methodDecl .getLeadingAnnotations ()) {
133+ JavaType .FullyQualified aType = TypeUtils .asFullyQualified (a .getType ());
134+ if (aType != null && BEAN_ANNOTATION_MATCHER .matchesAnnotationOrMetaAnnotation (aType )) {
135+ return true ;
136+ }
137+ }
138+ return false ;
139+ }
140140}
0 commit comments