@@ -516,6 +516,7 @@ def translate_stmt_list(
516516 codes .FILE .code
517517 )
518518 block = Block (self .fix_function_overloads (self .translate_stmt_list (stmts )))
519+ self .set_block_lines (block , stmts )
519520 mark_block_unreachable (block )
520521 return [block ]
521522
@@ -611,30 +612,38 @@ def from_comp_operator(self, op: ast3.cmpop) -> str:
611612 else :
612613 return op_name
613614
614- def as_block (self , stmts : list [ast3 .stmt ], lineno : int ) -> Block | None :
615+ def set_block_lines (self , b : Block , stmts : Sequence [ast3 .stmt ]) -> None :
616+ first , last = stmts [0 ], stmts [- 1 ]
617+ b .line = first .lineno
618+ b .column = first .col_offset
619+ b .end_line = getattr (last , "end_lineno" , None )
620+ b .end_column = getattr (last , "end_col_offset" , None )
621+ if not b .body :
622+ return
623+ new_first = b .body [0 ]
624+ if isinstance (new_first , (Decorator , OverloadedFuncDef )):
625+ # Decorated function lines are different between Python versions.
626+ # copy the normalization we do for them to block first lines.
627+ b .line = new_first .line
628+ b .column = new_first .column
629+
630+ def as_block (self , stmts : list [ast3 .stmt ]) -> Block | None :
615631 b = None
616632 if stmts :
617633 b = Block (self .fix_function_overloads (self .translate_stmt_list (stmts )))
618- b . set_line ( lineno )
634+ self . set_block_lines ( b , stmts )
619635 return b
620636
621637 def as_required_block (
622- self ,
623- stmts : list [ast3 .stmt ],
624- lineno : int ,
625- * ,
626- can_strip : bool = False ,
627- is_coroutine : bool = False ,
638+ self , stmts : list [ast3 .stmt ], * , can_strip : bool = False , is_coroutine : bool = False
628639 ) -> Block :
629640 assert stmts # must be non-empty
630641 b = Block (
631642 self .fix_function_overloads (
632643 self .translate_stmt_list (stmts , can_strip = can_strip , is_coroutine = is_coroutine )
633644 )
634645 )
635- # TODO: in most call sites line is wrong (includes first line of enclosing statement)
636- # TODO: also we need to set the column, and the end position here.
637- b .set_line (lineno )
646+ self .set_block_lines (b , stmts )
638647 return b
639648
640649 def fix_function_overloads (self , stmts : list [Statement ]) -> list [Statement ]:
@@ -1023,7 +1032,7 @@ def do_func_def(
10231032
10241033 self .class_and_function_stack .pop ()
10251034 self .class_and_function_stack .append ("F" )
1026- body = self .as_required_block (n .body , lineno , can_strip = True , is_coroutine = is_coroutine )
1035+ body = self .as_required_block (n .body , can_strip = True , is_coroutine = is_coroutine )
10271036 func_def = FuncDef (n .name , args , body , func_type )
10281037 if isinstance (func_def .type , CallableType ):
10291038 # semanal.py does some in-place modifications we want to avoid
@@ -1052,9 +1061,6 @@ def do_func_def(
10521061 func_def .is_decorated = True
10531062 func_def .deco_line = deco_line
10541063 func_def .set_line (lineno , n .col_offset , end_line , end_column )
1055- # Set the line again after we updated it (to make value same in Python 3.7/3.8)
1056- # Note that TODOs in as_required_block() apply here as well.
1057- func_def .body .set_line (lineno )
10581064
10591065 deco = Decorator (func_def , self .translate_expr_list (n .decorator_list ), var )
10601066 first = n .decorator_list [0 ]
@@ -1165,7 +1171,7 @@ def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
11651171
11661172 cdef = ClassDef (
11671173 n .name ,
1168- self .as_required_block (n .body , n . lineno ),
1174+ self .as_required_block (n .body ),
11691175 None ,
11701176 self .translate_expr_list (n .bases ),
11711177 metaclass = dict (keywords ).get ("metaclass" ),
@@ -1237,8 +1243,8 @@ def visit_For(self, n: ast3.For) -> ForStmt:
12371243 node = ForStmt (
12381244 self .visit (n .target ),
12391245 self .visit (n .iter ),
1240- self .as_required_block (n .body , n . lineno ),
1241- self .as_block (n .orelse , n . lineno ),
1246+ self .as_required_block (n .body ),
1247+ self .as_block (n .orelse ),
12421248 target_type ,
12431249 )
12441250 return self .set_line (node , n )
@@ -1249,8 +1255,8 @@ def visit_AsyncFor(self, n: ast3.AsyncFor) -> ForStmt:
12491255 node = ForStmt (
12501256 self .visit (n .target ),
12511257 self .visit (n .iter ),
1252- self .as_required_block (n .body , n . lineno ),
1253- self .as_block (n .orelse , n . lineno ),
1258+ self .as_required_block (n .body ),
1259+ self .as_block (n .orelse ),
12541260 target_type ,
12551261 )
12561262 node .is_async = True
@@ -1259,19 +1265,14 @@ def visit_AsyncFor(self, n: ast3.AsyncFor) -> ForStmt:
12591265 # While(expr test, stmt* body, stmt* orelse)
12601266 def visit_While (self , n : ast3 .While ) -> WhileStmt :
12611267 node = WhileStmt (
1262- self .visit (n .test ),
1263- self .as_required_block (n .body , n .lineno ),
1264- self .as_block (n .orelse , n .lineno ),
1268+ self .visit (n .test ), self .as_required_block (n .body ), self .as_block (n .orelse )
12651269 )
12661270 return self .set_line (node , n )
12671271
12681272 # If(expr test, stmt* body, stmt* orelse)
12691273 def visit_If (self , n : ast3 .If ) -> IfStmt :
1270- lineno = n .lineno
12711274 node = IfStmt (
1272- [self .visit (n .test )],
1273- [self .as_required_block (n .body , lineno )],
1274- self .as_block (n .orelse , lineno ),
1275+ [self .visit (n .test )], [self .as_required_block (n .body )], self .as_block (n .orelse )
12751276 )
12761277 return self .set_line (node , n )
12771278
@@ -1281,7 +1282,7 @@ def visit_With(self, n: ast3.With) -> WithStmt:
12811282 node = WithStmt (
12821283 [self .visit (i .context_expr ) for i in n .items ],
12831284 [self .visit (i .optional_vars ) for i in n .items ],
1284- self .as_required_block (n .body , n . lineno ),
1285+ self .as_required_block (n .body ),
12851286 target_type ,
12861287 )
12871288 return self .set_line (node , n )
@@ -1292,7 +1293,7 @@ def visit_AsyncWith(self, n: ast3.AsyncWith) -> WithStmt:
12921293 s = WithStmt (
12931294 [self .visit (i .context_expr ) for i in n .items ],
12941295 [self .visit (i .optional_vars ) for i in n .items ],
1295- self .as_required_block (n .body , n . lineno ),
1296+ self .as_required_block (n .body ),
12961297 target_type ,
12971298 )
12981299 s .is_async = True
@@ -1309,15 +1310,15 @@ def visit_Try(self, n: ast3.Try) -> TryStmt:
13091310 self .set_line (NameExpr (h .name ), h ) if h .name is not None else None for h in n .handlers
13101311 ]
13111312 types = [self .visit (h .type ) for h in n .handlers ]
1312- handlers = [self .as_required_block (h .body , h . lineno ) for h in n .handlers ]
1313+ handlers = [self .as_required_block (h .body ) for h in n .handlers ]
13131314
13141315 node = TryStmt (
1315- self .as_required_block (n .body , n . lineno ),
1316+ self .as_required_block (n .body ),
13161317 vs ,
13171318 types ,
13181319 handlers ,
1319- self .as_block (n .orelse , n . lineno ),
1320- self .as_block (n .finalbody , n . lineno ),
1320+ self .as_block (n .orelse ),
1321+ self .as_block (n .finalbody ),
13211322 )
13221323 return self .set_line (node , n )
13231324
@@ -1326,15 +1327,15 @@ def visit_TryStar(self, n: TryStar) -> TryStmt:
13261327 self .set_line (NameExpr (h .name ), h ) if h .name is not None else None for h in n .handlers
13271328 ]
13281329 types = [self .visit (h .type ) for h in n .handlers ]
1329- handlers = [self .as_required_block (h .body , h . lineno ) for h in n .handlers ]
1330+ handlers = [self .as_required_block (h .body ) for h in n .handlers ]
13301331
13311332 node = TryStmt (
1332- self .as_required_block (n .body , n . lineno ),
1333+ self .as_required_block (n .body ),
13331334 vs ,
13341335 types ,
13351336 handlers ,
1336- self .as_block (n .orelse , n . lineno ),
1337- self .as_block (n .finalbody , n . lineno ),
1337+ self .as_block (n .orelse ),
1338+ self .as_block (n .finalbody ),
13381339 )
13391340 node .is_star = True
13401341 return self .set_line (node , n )
@@ -1469,9 +1470,7 @@ def visit_Lambda(self, n: ast3.Lambda) -> LambdaExpr:
14691470 body .col_offset = n .body .col_offset
14701471
14711472 self .class_and_function_stack .append ("L" )
1472- e = LambdaExpr (
1473- self .transform_args (n .args , n .lineno ), self .as_required_block ([body ], n .lineno )
1474- )
1473+ e = LambdaExpr (self .transform_args (n .args , n .lineno ), self .as_required_block ([body ]))
14751474 self .class_and_function_stack .pop ()
14761475 e .set_line (n .lineno , n .col_offset ) # Overrides set_line -- can't use self.set_line
14771476 return e
@@ -1743,7 +1742,7 @@ def visit_Match(self, n: Match) -> MatchStmt:
17431742 self .visit (n .subject ),
17441743 [self .visit (c .pattern ) for c in n .cases ],
17451744 [self .visit (c .guard ) for c in n .cases ],
1746- [self .as_required_block (c .body , n . lineno ) for c in n .cases ],
1745+ [self .as_required_block (c .body ) for c in n .cases ],
17471746 )
17481747 return self .set_line (node , n )
17491748
0 commit comments