12
12
13
13
from __future__ import annotations
14
14
15
- from typing import TYPE_CHECKING , Any
15
+ from typing import TYPE_CHECKING , Any , TypeAlias
16
16
17
17
from astroid import nodes
18
18
23
23
if TYPE_CHECKING :
24
24
from pylint .lint import PyLinter
25
25
26
+ SimpleNode : TypeAlias = (
27
+ nodes .Assert
28
+ | nodes .Assign
29
+ | nodes .AugAssign
30
+ | nodes .Delete
31
+ | nodes .Raise
32
+ | nodes .Yield
33
+ | nodes .Import
34
+ | nodes .Call
35
+ | nodes .Subscript
36
+ | nodes .Pass
37
+ | nodes .Continue
38
+ | nodes .Break
39
+ | nodes .Global
40
+ | nodes .Return
41
+ | nodes .Expr
42
+ | nodes .Await
43
+ )
44
+
26
45
27
46
class PathGraph :
28
47
def __init__ (self ) -> None :
@@ -58,14 +77,42 @@ def __init__(self) -> None:
58
77
self .tail : Any = None
59
78
60
79
def dispatch (self , node : nodes .NodeNG ) -> None :
61
- meth = getattr (self , "visit" + node .__class__ .__name__ , self .default )
62
- meth (node )
80
+ {
81
+ "FunctionDef" : self .visitFunctionDef ,
82
+ "AsyncFunctionDef" : self .visitFunctionDef ,
83
+ "With" : self .visitWith ,
84
+ "AsyncWith" : self .visitWith ,
85
+ "For" : self .visitFor ,
86
+ "AsyncFor" : self .visitFor ,
87
+ "While" : self .visitFor ,
88
+ "If" : self .visitFor ,
89
+ "Try" : self .visitTry ,
90
+ "Match" : self .visitMatch ,
91
+ "Assert" : self .visitSimpleNode ,
92
+ "Assign" : self .visitSimpleNode ,
93
+ "AugAssign" : self .visitSimpleNode ,
94
+ "Delete" : self .visitSimpleNode ,
95
+ "Raise" : self .visitSimpleNode ,
96
+ "Yield" : self .visitSimpleNode ,
97
+ "Import" : self .visitSimpleNode ,
98
+ "Call" : self .visitSimpleNode ,
99
+ "Subscript" : self .visitSimpleNode ,
100
+ "Pass" : self .visitSimpleNode ,
101
+ "Continue" : self .visitSimpleNode ,
102
+ "Break" : self .visitSimpleNode ,
103
+ "Global" : self .visitSimpleNode ,
104
+ "Return" : self .visitSimpleNode ,
105
+ "Expr" : self .visitSimpleNode ,
106
+ "Await" : self .visitSimpleNode ,
107
+ }.get (node .__class__ .__name__ , self .default )(node )
63
108
64
109
def default (self , node : nodes .NodeNG ) -> None :
65
110
for child in node .get_children ():
66
111
self .dispatch (child )
67
112
68
- def visitFunctionDef (self , node : nodes .FunctionDef ) -> None :
113
+ def visitFunctionDef (
114
+ self , node : nodes .FunctionDef | nodes .AsyncFunctionDef
115
+ ) -> None :
69
116
if self .graph is not None :
70
117
# closure
71
118
self .graph .connect (self .tail , node )
@@ -86,33 +133,23 @@ def visitFunctionDef(self, node: nodes.FunctionDef) -> None:
86
133
self .graph = None
87
134
self .tail = None
88
135
89
- visitAsyncFunctionDef = visitFunctionDef
90
-
91
- def visitAssert (self , node : nodes .NodeNG ) -> None :
136
+ def visitSimpleNode (self , node : SimpleNode ) -> None :
92
137
if self .tail and self .graph :
93
138
self .graph .connect (self .tail , node )
94
139
self .tail = node
95
140
96
- visitAssign = visitAugAssign = visitDelete = visitRaise = visitYield = (
97
- visitImport
98
- ) = visitCall = visitSubscript = visitPass = visitContinue = visitBreak = (
99
- visitGlobal
100
- ) = visitReturn = visitExpr = visitAwait = visitAssert
101
-
102
- def visitWith (self , node : nodes .With ) -> None :
141
+ def visitWith (self , node : nodes .With | nodes .AsyncWith ) -> None :
103
142
if self .tail and self .graph :
104
143
self .graph .connect (self .tail , node )
105
144
self .tail = node
106
145
for child in node .body :
107
146
self .dispatch (child )
108
147
109
- visitAsyncWith = visitWith
110
-
111
- def visitFor ( self , node : nodes . For | nodes . While ) -> None :
148
+ def visitFor (
149
+ self , node : nodes . For | nodes . AsyncFor | nodes . While | nodes . If
150
+ ) -> None :
112
151
self ._subgraph (node , node .handlers if isinstance (node , nodes .Try ) else [])
113
152
114
- visitAsyncFor = visitWhile = visitIf = visitFor
115
-
116
153
def visitTry (self , node : nodes .Try ) -> None :
117
154
self ._subgraph (node , node .handlers )
118
155
0 commit comments