Skip to content

Commit 8fa18c7

Browse files
authored
Handle FunctionDef blockstart_tolineno edge cases (#2880)
Getting the lineno of the start of the block for function definition(`FunctionDef.blockstart_tolineno`) can be quite tricky. Take below example: ```python # Case A def foo(bar: str) -> None: pass # should returns line=1 # Case B def foo( bar:str): pass # should returns line=2 # Case C def foo( bar:str ) -> None: pass # should returns line=3 # Case D def foo( bar:str ): # should returns line=3 pass ``` Currently we only handled Case A, B. With this commit we can cover case C. But for Case D, we will need a better solution
1 parent ff7205c commit 8fa18c7

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

astroid/nodes/scoped_nodes/scoped_nodes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,8 @@ def blockstart_tolineno(self):
14011401
14021402
:type: int
14031403
"""
1404+
if self.returns:
1405+
return self.returns.tolineno
14041406
return self.args.tolineno
14051407

14061408
def implicit_parameters(self) -> Literal[0, 1]:

tests/test_scoped_nodes.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,46 @@ def foo():
982982
with pytest.raises(AttributeInferenceError):
983983
func.getattr("")
984984

985+
@staticmethod
986+
def test_blockstart_tolineno() -> None:
987+
code = textwrap.dedent(
988+
"""\
989+
def f1(bar: str) -> None: #@
990+
pass
991+
992+
def f2( #@
993+
bar: str) -> None:
994+
pass
995+
996+
def f3( #@
997+
bar: str
998+
) -> None:
999+
pass
1000+
1001+
def f4( #@
1002+
bar: str
1003+
):
1004+
pass
1005+
1006+
def f5( #@
1007+
bar: str):
1008+
pass
1009+
"""
1010+
)
1011+
ast_nodes: list[nodes.FunctionDef] = builder.extract_node(code) # type: ignore[assignment]
1012+
assert len(ast_nodes) == 5
1013+
1014+
assert ast_nodes[0].blockstart_tolineno == 1
1015+
1016+
assert ast_nodes[1].blockstart_tolineno == 5
1017+
1018+
assert ast_nodes[2].blockstart_tolineno == 10
1019+
1020+
# Unimplemented, will return line 14 for now.
1021+
# assert ast_nodes[3].blockstart_tolineno == 15
1022+
1023+
assert ast_nodes[4].blockstart_tolineno == 19
1024+
9851025

9861026
class ClassNodeTest(ModuleLoader, unittest.TestCase):
9871027
def test_dict_interface(self) -> None:

0 commit comments

Comments
 (0)