2727import org .sonar .java .checks .helpers .MethodTreeUtils ;
2828import org .sonar .plugins .java .api .IssuableSubscriptionVisitor ;
2929import org .sonar .plugins .java .api .semantic .Symbol ;
30+ import org .sonar .plugins .java .api .semantic .SymbolMetadata ;
3031import org .sonar .plugins .java .api .tree .AnnotationTree ;
31- import org .sonar .plugins .java .api .tree .Arguments ;
32- import org .sonar .plugins .java .api .tree .AssignmentExpressionTree ;
3332import org .sonar .plugins .java .api .tree .ClassTree ;
34- import org .sonar .plugins .java .api .tree .IdentifierTree ;
35- import org .sonar .plugins .java .api .tree .LiteralTree ;
36- import org .sonar .plugins .java .api .tree .MemberSelectExpressionTree ;
3733import org .sonar .plugins .java .api .tree .MethodTree ;
3834import org .sonar .plugins .java .api .tree .Tree ;
3935import org .sonar .plugins .java .api .tree .VariableTree ;
@@ -45,7 +41,6 @@ public class NonSingletonAutowiredInSingletonCheck extends IssuableSubscriptionV
4541 private static final String JAVAX_INJECT_ANNOTATION = "javax.inject.Inject" ;
4642 private static final String JAKARTA_INJECT_ANNOTATION = "jakarta.inject.Inject" ;
4743 private static final Set <String > AUTO_WIRING_ANNOTATIONS = Set .of (AUTOWIRED_ANNOTATION , JAVAX_INJECT_ANNOTATION , JAKARTA_INJECT_ANNOTATION );
48- private static final Set <String > SINGLETON_LITERALS = Set .of ("singleton" , "\" singleton\" " );
4944
5045 @ Override
5146 public List <Tree .Kind > nodesToVisit () {
@@ -157,57 +152,32 @@ private void reportIfNonSingletonInSingleton(ClassTree enclosingClassTree, Varia
157152 }
158153
159154 private static boolean hasTypeNotSingletonBean (VariableTree variableTree ) {
160- var typeSymbolDeclaration = variableTree .type ().symbolType ().symbol ().declaration ();
161- return typeSymbolDeclaration != null && hasNotSingletonScopeAnnotation (typeSymbolDeclaration .modifiers ().annotations ());
155+ return hasNotSingletonScopeAnnotation (variableTree .symbol ().type ().symbol ().metadata ().annotations ());
162156 }
163157
164158 private static boolean isAutoWiringAnnotation (AnnotationTree annotationTree ) {
165159 return AUTO_WIRING_ANNOTATIONS .contains (annotationTree .symbolType ().fullyQualifiedName ());
166160 }
167161
168162 private static boolean isSingletonBean (ClassTree classTree ) {
169- return !hasNotSingletonScopeAnnotation (classTree .modifiers ().annotations ());
163+ return !hasNotSingletonScopeAnnotation (classTree .symbol (). metadata ().annotations ());
170164 }
171165
172- private static boolean hasNotSingletonScopeAnnotation (List <AnnotationTree > annotations ) {
166+ private static boolean hasNotSingletonScopeAnnotation (List <SymbolMetadata . AnnotationInstance > annotations ) {
173167 // Only classes annotated with @Scope, having a value different from "singleton", are considered as non-Singleton
174168 return annotations .stream ().anyMatch (NonSingletonAutowiredInSingletonCheck ::isNotSingletonScopeAnnotation );
175169 }
176170
177- private static boolean isNotSingletonScopeAnnotation (AnnotationTree annotationTree ) {
178- return annotationTree .symbolType ().is (SCOPED_ANNOTATION )
179- && (isNotSingletonLiteralValue (annotationTree .arguments ()) || isNotSingletonAssignmentValue (annotationTree .arguments ()));
171+ private static boolean isNotSingletonScopeAnnotation (SymbolMetadata .AnnotationInstance annotationInstance ) {
172+ return annotationInstance .symbol ().type ().is (SCOPED_ANNOTATION )
173+ && annotationInstance .values ()
174+ .stream ()
175+ .anyMatch (NonSingletonAutowiredInSingletonCheck ::isNotSingletonAnnotationValue );
180176 }
181177
182- private static boolean isNotSingletonLiteralValue ( Arguments arguments ) {
183- return arguments . size () == 1
184- && arguments . get ( 0 ). is ( Tree . Kind . STRING_LITERAL )
185- && isNotSingletonLiteral ((( LiteralTree ) arguments . get ( 0 )) .value ());
178+ private static boolean isNotSingletonAnnotationValue ( SymbolMetadata . AnnotationValue annotationValue ) {
179+ return ( "value" . equals ( annotationValue . name ()) || "scopeName" . equals ( annotationValue . name ()))
180+ // both "value" and "scopeName" in @Scope annotation have String type
181+ && ! "singleton" . equalsIgnoreCase (( String ) annotationValue .value ());
186182 }
187-
188- private static boolean isNotSingletonAssignmentValue (Arguments arguments ) {
189- return arguments
190- .stream ()
191- .filter (argument -> argument .is (Tree .Kind .ASSIGNMENT ))
192- .map (AssignmentExpressionTree .class ::cast )
193- .anyMatch (NonSingletonAutowiredInSingletonCheck ::isNotAssignmentToSingletonValue );
194- }
195-
196- private static boolean isNotAssignmentToSingletonValue (AssignmentExpressionTree assignmentExpressionTree ) {
197- var expression = assignmentExpressionTree .expression ();
198-
199- if (expression .is (Tree .Kind .STRING_LITERAL )) {
200- return isNotSingletonLiteral (((LiteralTree ) expression ).value ());
201- }
202-
203- var variable = (IdentifierTree ) assignmentExpressionTree .variable ();
204-
205- return ("value" .equals (variable .name ()) || "scopeName" .equals (variable .name ()))
206- && (expression .is (Tree .Kind .MEMBER_SELECT ) && isNotSingletonLiteral (((MemberSelectExpressionTree ) expression ).identifier ().name ()));
207- }
208-
209- private static boolean isNotSingletonLiteral (String value ) {
210- return SINGLETON_LITERALS .stream ().noneMatch (singletonLiteral -> singletonLiteral .equalsIgnoreCase (value ));
211- }
212-
213183}
0 commit comments