11import ast
22from typing import Optional , Set , Union
33
4- from .utils import ErrorVisitor , is_component_def , is_hook_def , set_current
4+ from .common import CheckContext , set_current
55
66HOOKS_WITH_DEPS = ("use_effect" , "use_callback" , "use_memo" )
77
88
9- class ExhaustiveDepsVisitor (ErrorVisitor ):
10- def __init__ (self ) -> None :
11- super ().__init__ ()
12- self ._current_function : Optional [ast .FunctionDef ] = None
9+ class ExhaustiveDepsVisitor (ast .NodeVisitor ):
10+ def __init__ (self , context : CheckContext ) -> None :
11+ self ._context = context
1312 self ._current_hook_or_component : Optional [ast .FunctionDef ] = None
1413
1514 def visit_FunctionDef (self , node : ast .FunctionDef ) -> None :
16- if is_hook_def (node ) or is_component_def (node ):
15+ if self . _context . is_hook_def (node ) or self . _context . is_component_def (node ):
1716 with set_current (self , hook_or_component = node ):
1817 self .generic_visit (node )
1918 elif self ._current_hook_or_component is not None :
@@ -53,10 +52,10 @@ def visit_Call(self, node: ast.Call) -> None:
5352 elif isinstance (called_func , ast .Attribute ):
5453 called_func_name = called_func .attr
5554 else : # pragma: no cover
56- return None
55+ return
5756
5857 if called_func_name not in HOOKS_WITH_DEPS :
59- return None
58+ return
6059
6160 func : Optional [ast .expr ] = None
6261 args : Optional [ast .expr ] = None
@@ -101,6 +100,7 @@ def _check_hook_dependency_list_is_exhaustive(
101100 variables_defined_in_scope = top_level_variable_finder .variable_names
102101
103102 missing_name_finder = _MissingNameFinder (
103+ self ._context ,
104104 hook_name = hook_name ,
105105 func_name = func_name ,
106106 dep_names = dep_names ,
@@ -113,8 +113,6 @@ def _check_hook_dependency_list_is_exhaustive(
113113 else :
114114 missing_name_finder .visit (func .body )
115115
116- self .errors .extend (missing_name_finder .errors )
117-
118116 def _get_dependency_names_from_expression (
119117 self , hook_name : str , dependency_expr : Optional [ast .expr ]
120118 ) -> Optional [Set [str ]]:
@@ -129,7 +127,7 @@ def _get_dependency_names_from_expression(
129127 # ideally we could deal with some common use cases, but since React's
130128 # own linter doesn't do this we'll just take the easy route for now:
131129 # https://github.com/facebook/react/issues/16265
132- self ._save_error (
130+ self ._context . add_error (
133131 200 ,
134132 elt ,
135133 (
@@ -143,7 +141,7 @@ def _get_dependency_names_from_expression(
143141 isinstance (dependency_expr , (ast .Constant , ast .NameConstant ))
144142 and dependency_expr .value is None
145143 ):
146- self ._save_error (
144+ self ._context . add_error (
147145 201 ,
148146 dependency_expr ,
149147 (
@@ -156,16 +154,17 @@ def _get_dependency_names_from_expression(
156154 return set ()
157155
158156
159- class _MissingNameFinder (ErrorVisitor ):
157+ class _MissingNameFinder (ast . NodeVisitor ):
160158 def __init__ (
161159 self ,
160+ context : CheckContext ,
162161 hook_name : str ,
163162 func_name : str ,
164163 dep_names : Set [str ],
165164 ignore_names : Set [str ],
166165 names_in_scope : Set [str ],
167166 ) -> None :
168- super (). __init__ ()
167+ self . _context = context
169168 self ._hook_name = hook_name
170169 self ._func_name = func_name
171170 self ._ignore_names = ignore_names
@@ -179,7 +178,7 @@ def visit_Name(self, node: ast.Name) -> None:
179178 if node_id in self ._dep_names :
180179 self .used_deps .add (node_id )
181180 else :
182- self ._save_error (
181+ self ._context . add_error (
183182 202 ,
184183 node ,
185184 (
0 commit comments