Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit c5d17f8

Browse files
committed
fix bug where nested element def treated as hook
1 parent ec60f1c commit c5d17f8

File tree

4 files changed

+23
-9
lines changed

4 files changed

+23
-9
lines changed

flake8_idom_hooks/exhaustive_deps.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import ast
22
from typing import Optional, List, Union, Set
33

4-
from .utils import is_hook_or_element_def, ErrorVisitor
4+
from .utils import is_hook_def, is_element_def, ErrorVisitor
55

66

77
HOOKS_WITH_DEPS = ("use_effect", "use_callback", "use_memo")
@@ -13,7 +13,7 @@ def __init__(self) -> None:
1313
self._current_hook_or_element: Optional[ast.FunctionDef] = None
1414

1515
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
16-
if is_hook_or_element_def(node):
16+
if is_hook_def(node) or is_element_def(node):
1717
self._current_hook_or_element = node
1818
self.generic_visit(node)
1919
self._current_hook_or_element = None

flake8_idom_hooks/rules_of_hooks.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@
22
from contextlib import contextmanager
33
from typing import Iterator, Union, Optional, Any
44

5-
from .utils import is_hook_or_element_def, ErrorVisitor, is_hook_function_name
5+
from .utils import is_hook_def, is_element_def, ErrorVisitor, is_hook_function_name
66

77

88
class RulesOfHooksVisitor(ErrorVisitor):
99
def __init__(self) -> None:
1010
super().__init__()
11-
self._current_hook_or_element: Optional[ast.FunctionDef] = None
11+
self._current_hook: Optional[ast.FunctionDef] = None
12+
self._current_element: Optional[ast.FunctionDef] = None
1213
self._current_function: Optional[ast.FunctionDef] = None
1314
self._current_call: Optional[ast.Call] = None
1415
self._current_conditional: Union[None, ast.If, ast.IfExp, ast.Try] = None
1516
self._current_loop: Union[None, ast.For, ast.While] = None
1617

1718
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
18-
if is_hook_or_element_def(node):
19+
if is_hook_def(node):
1920
self._check_if_hook_defined_in_function(node)
20-
with self._set_current(hook_or_element=node, function=node):
21+
with self._set_current(hook=node, function=node):
22+
self.generic_visit(node)
23+
elif is_element_def(node):
24+
with self._set_current(element=node, function=node):
2125
self.generic_visit(node)
2226
else:
2327
with self._set_current(function=node):
@@ -60,7 +64,7 @@ def _check_if_propper_hook_usage(
6064
if not is_hook_function_name(name):
6165
return None
6266

63-
if self._current_hook_or_element is None:
67+
if self._current_hook is None and self._current_element is None:
6468
msg = f"hook {name!r} used outside element or hook definition"
6569
self._save_error(101, node, msg)
6670

flake8_idom_hooks/utils.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ def _save_error(self, error_code: int, node: ast.AST, message: str) -> None:
1010
self.errors.append((node.lineno, node.col_offset, f"ROH{error_code} {message}"))
1111

1212

13-
def is_hook_or_element_def(node: ast.FunctionDef) -> bool:
14-
return is_element_function_name(node.name) or is_hook_function_name(node.name)
13+
def is_hook_def(node: ast.FunctionDef) -> bool:
14+
return is_hook_function_name(node.name)
15+
16+
17+
def is_element_def(node: ast.FunctionDef) -> bool:
18+
return is_element_function_name(node.name)
1519

1620

1721
def is_element_function_name(name: str) -> bool:

tests/hook_usage_test_cases.py

+6
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,9 @@ def impropper_usage_of_effect_as_decorator():
200200
# error: ROH202 dependency args of 'use_effect' should be a literal list or tuple - not expression type 'Name'
201201
not_a_list_or_tuple,
202202
)
203+
204+
205+
def make_element():
206+
# nested element definitions are ok.
207+
def NestedElement():
208+
use_state

0 commit comments

Comments
 (0)