3737import org .sonar .squidbridge .annotations .SqaleConstantRemediation ;
3838import org .sonar .squidbridge .annotations .SqaleSubCharacteristic ;
3939
40+ import javax .annotation .Nullable ;
4041import java .util .HashMap ;
41- import java .util .HashSet ;
4242import java .util .List ;
4343import java .util .Map ;
44- import java .util .Set ;
4544
4645@ Rule (
4746 key = "S3047" ,
@@ -61,41 +60,42 @@ public List<Tree.Kind> nodesToVisit() {
6160 @ Override
6261 public void visitNode (Tree tree ) {
6362 Map <Symbol , Integer > forEachSymbols = new HashMap <>();
64- Set < Tree > forEachIterables = new HashSet <>() ;
63+ Tree previousForeachIterable = null ;
6564 for (Tree item : ((BlockTree ) tree ).body ()) {
6665 if (item .is (Tree .Kind .FOR_EACH_STATEMENT )) {
67- checkForEach (forEachSymbols , forEachIterables , (ForEachStatement ) item );
66+ ForEachStatement forEachStatement = (ForEachStatement ) item ;
67+ checkForEach (forEachSymbols , previousForeachIterable , forEachStatement );
68+ previousForeachIterable = forEachStatement .expression ();
6869 } else {
70+ previousForeachIterable = null ;
6971 item .accept (new InvalidatorVisitor (forEachSymbols ));
7072 }
7173 }
7274 }
7375
74- private void checkForEach (Map <Symbol , Integer > forEachSymbols , Set < Tree > forEachIterables , ForEachStatement item ) {
76+ private void checkForEach (Map <Symbol , Integer > forEachSymbols , @ Nullable Tree previousIterable , ForEachStatement item ) {
7577 ExpressionTree expressionTree = ExpressionsHelper .skipParentheses (item .expression ());
7678 if (expressionTree .is (Tree .Kind .IDENTIFIER )) {
7779 checkForEachIdentifier (forEachSymbols , (IdentifierTree ) expressionTree );
78- } else {
79- checkForEachExpression (forEachIterables , expressionTree );
80+ } else if ( previousIterable != null ) {
81+ checkForEachExpression (previousIterable , expressionTree );
8082 }
8183 }
8284
83- private void checkForEachExpression (Set <Tree > forEachIterables , ExpressionTree expressionTree ) {
84- for (Tree subTree : forEachIterables ) {
85- if (SyntacticEquivalence .areEquivalent (expressionTree , subTree )) {
86- addIssue (expressionTree , FirstSyntaxTokenFinder .firstSyntaxToken (subTree ).line ());
87- return ;
88- }
85+ private void checkForEachExpression (Tree forEachIterable , ExpressionTree expressionTree ) {
86+ if (SyntacticEquivalence .areEquivalent (expressionTree , forEachIterable )) {
87+ addIssue (expressionTree , FirstSyntaxTokenFinder .firstSyntaxToken (forEachIterable ).line ());
8988 }
90- forEachIterables .add (expressionTree );
9189 }
9290
9391 private void checkForEachIdentifier (Map <Symbol , Integer > forEachSymbols , IdentifierTree node ) {
9492 Symbol symbol = node .symbol ();
95- if (forEachSymbols .containsKey (symbol )) {
96- addIssue (node , forEachSymbols .get (symbol ));
97- } else {
98- forEachSymbols .put (symbol , ((JavaTree ) node ).getLine ());
93+ if (symbol .owner ().isMethodSymbol ()) {
94+ if (forEachSymbols .containsKey (symbol )) {
95+ addIssue (node , forEachSymbols .get (symbol ));
96+ } else {
97+ forEachSymbols .put (symbol , ((JavaTree ) node ).getLine ());
98+ }
9999 }
100100 }
101101
0 commit comments