6666 SetExpr ,
6767 SliceExpr ,
6868 StarExpr ,
69+ Statement ,
6970 StrExpr ,
7071 SuperExpr ,
7172 TempNode ,
9697 StarredPattern ,
9798 ValuePattern ,
9899)
99- from mypy .visitor import NodeVisitor
100+ from mypy .visitor import NodeVisitor , StatementVisitor
100101
101102
102103@trait
@@ -108,6 +109,10 @@ class TraverserVisitor(NodeVisitor[None]):
108109 should override visit methods to perform actions during
109110 traversal. Calling the superclass method allows reusing the
110111 traversal implementation.
112+
113+ TODO: split this into more limited visitor (e.g. statements-only etc).
114+ This will improve performance since in many cases we don't need to recurse
115+ all the way down in various visitors that subclass this.
111116 """
112117
113118 def __init__ (self ) -> None :
@@ -1084,3 +1089,115 @@ def visit_assignment_stmt(self, stmt: AssignmentStmt) -> None:
10841089
10851090 def visit_yield_from_expr (self , expr : YieldFromExpr ) -> None :
10861091 self .yield_from_expressions .append ((expr , self .in_assignment ))
1092+
1093+
1094+ def find_definitions (o : Statement , name : str ) -> list [Statement ]:
1095+ visitor = DefinitionSeeker (name )
1096+ o .accept (visitor )
1097+ return visitor .found
1098+
1099+
1100+ class DefinitionSeeker (StatementVisitor [None ]):
1101+ def __init__ (self , name : str ) -> None :
1102+ self .name = name
1103+ self .found : list [Statement ] = []
1104+
1105+ def visit_assignment_stmt (self , o : AssignmentStmt , / ) -> None :
1106+ # TODO: support more kinds of locations (like assignment statements).
1107+ # the latter will be helpful for type old-style aliases.
1108+ pass
1109+
1110+ def visit_for_stmt (self , o : ForStmt , / ) -> None :
1111+ o .body .accept (self )
1112+ if o .else_body :
1113+ o .else_body .accept (self )
1114+
1115+ def visit_with_stmt (self , o : WithStmt , / ) -> None :
1116+ o .body .accept (self )
1117+
1118+ def visit_del_stmt (self , o : DelStmt , / ) -> None :
1119+ pass
1120+
1121+ def visit_func_def (self , o : FuncDef , / ) -> None :
1122+ if o .name == self .name :
1123+ self .found .append (o )
1124+
1125+ def visit_overloaded_func_def (self , o : OverloadedFuncDef , / ) -> None :
1126+ if o .name == self .name :
1127+ self .found .append (o )
1128+
1129+ def visit_class_def (self , o : ClassDef , / ) -> None :
1130+ if o .name == self .name :
1131+ self .found .append (o )
1132+
1133+ def visit_global_decl (self , o : GlobalDecl , / ) -> None :
1134+ pass
1135+
1136+ def visit_nonlocal_decl (self , o : NonlocalDecl , / ) -> None :
1137+ pass
1138+
1139+ def visit_decorator (self , o : Decorator , / ) -> None :
1140+ if o .name == self .name :
1141+ self .found .append (o )
1142+
1143+ def visit_import (self , o : Import , / ) -> None :
1144+ pass
1145+
1146+ def visit_import_from (self , o : ImportFrom , / ) -> None :
1147+ pass
1148+
1149+ def visit_import_all (self , o : ImportAll , / ) -> None :
1150+ pass
1151+
1152+ def visit_block (self , o : Block , / ) -> None :
1153+ for s in o .body :
1154+ s .accept (self )
1155+
1156+ def visit_expression_stmt (self , o : ExpressionStmt , / ) -> None :
1157+ pass
1158+
1159+ def visit_operator_assignment_stmt (self , o : OperatorAssignmentStmt , / ) -> None :
1160+ pass
1161+
1162+ def visit_while_stmt (self , o : WhileStmt , / ) -> None :
1163+ o .body .accept (self )
1164+ if o .else_body :
1165+ o .else_body .accept (self )
1166+
1167+ def visit_return_stmt (self , o : ReturnStmt , / ) -> None :
1168+ pass
1169+
1170+ def visit_assert_stmt (self , o : AssertStmt , / ) -> None :
1171+ pass
1172+
1173+ def visit_if_stmt (self , o : IfStmt , / ) -> None :
1174+ for b in o .body :
1175+ b .accept (self )
1176+ if o .else_body :
1177+ o .else_body .accept (self )
1178+
1179+ def visit_break_stmt (self , o : BreakStmt , / ) -> None :
1180+ pass
1181+
1182+ def visit_continue_stmt (self , o : ContinueStmt , / ) -> None :
1183+ pass
1184+
1185+ def visit_pass_stmt (self , o : PassStmt , / ) -> None :
1186+ pass
1187+
1188+ def visit_raise_stmt (self , o : RaiseStmt , / ) -> None :
1189+ pass
1190+
1191+ def visit_try_stmt (self , o : TryStmt , / ) -> None :
1192+ o .body .accept (self )
1193+ if o .else_body is not None :
1194+ o .else_body .accept (self )
1195+ if o .finally_body is not None :
1196+ o .finally_body .accept (self )
1197+
1198+ def visit_match_stmt (self , o : MatchStmt , / ) -> None :
1199+ for b in o .bodies :
1200+ b .accept (self )
1201+
1202+ def visit_type_alias_stmt (self , o : TypeAliasStmt , / ) -> None :
1203+ pass
0 commit comments