2222import org .sonar .plugins .java .api .IssuableSubscriptionVisitor ;
2323import org .sonar .plugins .java .api .semantic .MethodMatchers ;
2424import org .sonar .plugins .java .api .tree .ExpressionTree ;
25+ import org .sonar .plugins .java .api .tree .LambdaExpressionTree ;
2526import org .sonar .plugins .java .api .tree .MemberSelectExpressionTree ;
2627import org .sonar .plugins .java .api .tree .MethodInvocationTree ;
2728import org .sonar .plugins .java .api .tree .Tree ;
29+ import org .sonar .plugins .java .api .tree .VariableTree ;
2830
29- import static org .sonar .java .matcher .TreeMatcher .any ;
3031import static org .sonar .java .matcher .TreeMatcher .calls ;
3132import static org .sonar .java .matcher .TreeMatcher .hasSize ;
33+ import static org .sonar .java .matcher .TreeMatcher .invokedOn ;
3234import static org .sonar .java .matcher .TreeMatcher .isExpression ;
35+ import static org .sonar .java .matcher .TreeMatcher .isIdentifier ;
3336import static org .sonar .java .matcher .TreeMatcher .isInvocationOf ;
3437import static org .sonar .java .matcher .TreeMatcher .statementAt ;
35- import static org .sonar .java .matcher .TreeMatcher .withBody ;
3638
3739@ Rule (key = "S7479" )
3840public class ClassBuilderWithMethodCheck extends IssuableSubscriptionVisitor {
@@ -49,16 +51,16 @@ public class ClassBuilderWithMethodCheck extends IssuableSubscriptionVisitor {
4951 .withAnyParameters ()
5052 .build ();
5153
52- /** Matches lambda expression composed of just a call to `MethodBuilder.withBody`. */
53- private final TreeMatcher <ExpressionTree > matcher = TreeMatcher
54- . isLambdaExpression (
55- withBody (
56- // Case with curly braces
57- hasSize ( 1 )
58- . and (
59- statementAt ( 0 , isInvocationOf ( withCode , any ())))
60- // Case with no curly braces
61- . or ( isExpression ( calls ( withCode , any ())))));
54+ /** Matches lambda bodies composed of just a call to `MethodBuilder.withBody` on the given variable . */
55+ private TreeMatcher <LambdaExpressionTree > makeMatcher ( VariableTree variableCalledOn ) {
56+ return TreeMatcher . withBody (
57+ // Case with curly braces
58+ hasSize ( 1 )
59+ . and (
60+ statementAt ( 0 , isInvocationOf ( withCode , invokedOn ( isIdentifier ( variableCalledOn . symbol ())))))
61+ // Case with no curly braces
62+ . or ( isExpression ( calls ( withCode , invokedOn ( isIdentifier ( variableCalledOn . symbol ()))))));
63+ }
6264
6365 @ Override
6466 public List <Tree .Kind > nodesToVisit () {
@@ -71,8 +73,12 @@ public void visitNode(Tree tree) {
7173 MethodInvocationTree invocation = (MethodInvocationTree ) tree ;
7274 if (withMethod .matches (invocation )) {
7375 ExpressionTree lastArgument = invocation .arguments ().get (invocation .arguments ().size () - 1 );
74- if (matcher .check (lastArgument )) {
75- reportIssue (findLocation (invocation ), "Replace call with `ClassBuilder.withMethodBody`." );
76+
77+ if (lastArgument instanceof LambdaExpressionTree lambda ) {
78+ VariableTree parameter = lambda .parameters ().get (0 );
79+ if (makeMatcher (parameter ).check (lambda )) {
80+ reportIssue (findLocation (invocation ), "Replace call with `ClassBuilder.withMethodBody`." );
81+ }
7682 }
7783 }
7884 }
0 commit comments