2121import org .sonar .check .Rule ;
2222import org .sonar .plugins .python .api .PythonSubscriptionCheck ;
2323import org .sonar .plugins .python .api .SubscriptionContext ;
24- import org .sonar .plugins .python .api .symbols .FunctionSymbol ;
25- import org .sonar .plugins .python .api .symbols .Symbol ;
24+ import org .sonar .plugins .python .api .symbols .v2 .SymbolV2 ;
25+ import org .sonar .plugins .python .api .types .v2 .FunctionType ;
26+ import org .sonar .plugins .python .api .types .v2 .matchers .TypeMatcher ;
27+ import org .sonar .plugins .python .api .types .v2 .matchers .TypeMatchers ;
2628import org .sonar .plugins .python .api .tree .BaseTreeVisitor ;
2729import org .sonar .plugins .python .api .tree .CallExpression ;
2830import org .sonar .plugins .python .api .tree .Expression ;
2931import org .sonar .plugins .python .api .tree .FunctionDef ;
32+ import org .sonar .plugins .python .api .tree .Name ;
33+ import org .sonar .plugins .python .api .tree .QualifiedExpression ;
3034import org .sonar .plugins .python .api .tree .Tree ;
31- import org .sonar .python .tree .TreeUtils ;
3235
3336@ Rule (key = "S6908" )
3437public class TfFunctionRecursivityCheck extends PythonSubscriptionCheck {
3538
3639 private static final String MESSAGE = "Make sure to avoid recursive calls in this function." ;
3740 private static final String SECONDARY_MESSAGE = "Recursive call is here." ;
41+ private static final TypeMatcher TENSORFLOW_FUNCTION_MATCHER = TypeMatchers .withFQN ("tensorflow.function" );
3842
3943 @ Override
4044 public void initialize (Context context ) {
@@ -43,14 +47,15 @@ public void initialize(Context context) {
4347
4448 private static void checkFunctionDef (SubscriptionContext context ) {
4549 FunctionDef functionDef = (FunctionDef ) context .syntaxNode ();
46- if (!TreeUtils . isFunctionWithGivenDecoratorFQN (functionDef , "tensorflow.function" )) {
50+ if (!hasTensorflowFunctionDecorator (functionDef , context )) {
4751 return ;
4852 }
49- FunctionSymbol functionSymbol = TreeUtils .getFunctionSymbolFromDef (functionDef );
50- if (functionSymbol == null ) {
53+ SymbolV2 functionSymbol = functionDef .name ().symbolV2 ();
54+ if (functionSymbol == null || functionSymbol .getSingleBindingUsage ().isEmpty ()
55+ || !(functionDef .name ().typeV2 () instanceof FunctionType functionType )) {
5156 return ;
5257 }
53- CallCollector collector = new CallCollector (functionSymbol );
58+ CallCollector collector = new CallCollector (functionSymbol , functionType );
5459 functionDef .accept (collector );
5560 if (collector .expressionList .isEmpty ()) {
5661 return ;
@@ -59,19 +64,28 @@ private static void checkFunctionDef(SubscriptionContext context) {
5964 collector .expressionList .forEach (call -> issue .secondary (call , SECONDARY_MESSAGE ));
6065 }
6166
67+ private static boolean hasTensorflowFunctionDecorator (FunctionDef functionDef , SubscriptionContext context ) {
68+ return functionDef .decorators ().stream ()
69+ .anyMatch (decorator -> TENSORFLOW_FUNCTION_MATCHER .isTrueFor (decorator .expression (), context ));
70+ }
71+
6272 private static class CallCollector extends BaseTreeVisitor {
63- private final Symbol originalSymbol ;
73+ private final SymbolV2 originalSymbol ;
74+ private final FunctionType originalType ;
6475 List <Expression > expressionList = new ArrayList <>();
6576
66- private CallCollector (Symbol originalSymbol ) {
77+ private CallCollector (SymbolV2 originalSymbol , FunctionType originalType ) {
6778 this .originalSymbol = originalSymbol ;
79+ this .originalType = originalType ;
6880 }
6981
7082 @ Override
7183 public void visitCallExpression (CallExpression callExpression ) {
72- TreeUtils .getSymbolFromTree (callExpression .callee ())
73- .filter (symbol -> symbol .equals (originalSymbol ))
74- .ifPresent (symbol -> expressionList .add (callExpression .callee ()));
84+ Expression callee = callExpression .callee ();
85+ if ((callee instanceof Name name && originalSymbol .equals (name .symbolV2 ()))
86+ || (callee instanceof QualifiedExpression && originalType .equals (callee .typeV2 ()))) {
87+ expressionList .add (callExpression .callee ());
88+ }
7589 super .visitCallExpression (callExpression );
7690 }
7791 }
0 commit comments