@@ -516,6 +516,7 @@ def translate_stmt_list(
516
516
codes .FILE .code
517
517
)
518
518
block = Block (self .fix_function_overloads (self .translate_stmt_list (stmts )))
519
+ self .set_block_lines (block , stmts )
519
520
mark_block_unreachable (block )
520
521
return [block ]
521
522
@@ -611,30 +612,38 @@ def from_comp_operator(self, op: ast3.cmpop) -> str:
611
612
else :
612
613
return op_name
613
614
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 :
615
631
b = None
616
632
if stmts :
617
633
b = Block (self .fix_function_overloads (self .translate_stmt_list (stmts )))
618
- b . set_line ( lineno )
634
+ self . set_block_lines ( b , stmts )
619
635
return b
620
636
621
637
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
628
639
) -> Block :
629
640
assert stmts # must be non-empty
630
641
b = Block (
631
642
self .fix_function_overloads (
632
643
self .translate_stmt_list (stmts , can_strip = can_strip , is_coroutine = is_coroutine )
633
644
)
634
645
)
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 )
638
647
return b
639
648
640
649
def fix_function_overloads (self , stmts : list [Statement ]) -> list [Statement ]:
@@ -1023,7 +1032,7 @@ def do_func_def(
1023
1032
1024
1033
self .class_and_function_stack .pop ()
1025
1034
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 )
1027
1036
func_def = FuncDef (n .name , args , body , func_type )
1028
1037
if isinstance (func_def .type , CallableType ):
1029
1038
# semanal.py does some in-place modifications we want to avoid
@@ -1052,9 +1061,6 @@ def do_func_def(
1052
1061
func_def .is_decorated = True
1053
1062
func_def .deco_line = deco_line
1054
1063
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 )
1058
1064
1059
1065
deco = Decorator (func_def , self .translate_expr_list (n .decorator_list ), var )
1060
1066
first = n .decorator_list [0 ]
@@ -1165,7 +1171,7 @@ def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
1165
1171
1166
1172
cdef = ClassDef (
1167
1173
n .name ,
1168
- self .as_required_block (n .body , n . lineno ),
1174
+ self .as_required_block (n .body ),
1169
1175
None ,
1170
1176
self .translate_expr_list (n .bases ),
1171
1177
metaclass = dict (keywords ).get ("metaclass" ),
@@ -1237,8 +1243,8 @@ def visit_For(self, n: ast3.For) -> ForStmt:
1237
1243
node = ForStmt (
1238
1244
self .visit (n .target ),
1239
1245
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 ),
1242
1248
target_type ,
1243
1249
)
1244
1250
return self .set_line (node , n )
@@ -1249,8 +1255,8 @@ def visit_AsyncFor(self, n: ast3.AsyncFor) -> ForStmt:
1249
1255
node = ForStmt (
1250
1256
self .visit (n .target ),
1251
1257
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 ),
1254
1260
target_type ,
1255
1261
)
1256
1262
node .is_async = True
@@ -1259,19 +1265,14 @@ def visit_AsyncFor(self, n: ast3.AsyncFor) -> ForStmt:
1259
1265
# While(expr test, stmt* body, stmt* orelse)
1260
1266
def visit_While (self , n : ast3 .While ) -> WhileStmt :
1261
1267
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 )
1265
1269
)
1266
1270
return self .set_line (node , n )
1267
1271
1268
1272
# If(expr test, stmt* body, stmt* orelse)
1269
1273
def visit_If (self , n : ast3 .If ) -> IfStmt :
1270
- lineno = n .lineno
1271
1274
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 )
1275
1276
)
1276
1277
return self .set_line (node , n )
1277
1278
@@ -1281,7 +1282,7 @@ def visit_With(self, n: ast3.With) -> WithStmt:
1281
1282
node = WithStmt (
1282
1283
[self .visit (i .context_expr ) for i in n .items ],
1283
1284
[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 ),
1285
1286
target_type ,
1286
1287
)
1287
1288
return self .set_line (node , n )
@@ -1292,7 +1293,7 @@ def visit_AsyncWith(self, n: ast3.AsyncWith) -> WithStmt:
1292
1293
s = WithStmt (
1293
1294
[self .visit (i .context_expr ) for i in n .items ],
1294
1295
[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 ),
1296
1297
target_type ,
1297
1298
)
1298
1299
s .is_async = True
@@ -1309,15 +1310,15 @@ def visit_Try(self, n: ast3.Try) -> TryStmt:
1309
1310
self .set_line (NameExpr (h .name ), h ) if h .name is not None else None for h in n .handlers
1310
1311
]
1311
1312
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 ]
1313
1314
1314
1315
node = TryStmt (
1315
- self .as_required_block (n .body , n . lineno ),
1316
+ self .as_required_block (n .body ),
1316
1317
vs ,
1317
1318
types ,
1318
1319
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 ),
1321
1322
)
1322
1323
return self .set_line (node , n )
1323
1324
@@ -1326,15 +1327,15 @@ def visit_TryStar(self, n: TryStar) -> TryStmt:
1326
1327
self .set_line (NameExpr (h .name ), h ) if h .name is not None else None for h in n .handlers
1327
1328
]
1328
1329
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 ]
1330
1331
1331
1332
node = TryStmt (
1332
- self .as_required_block (n .body , n . lineno ),
1333
+ self .as_required_block (n .body ),
1333
1334
vs ,
1334
1335
types ,
1335
1336
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 ),
1338
1339
)
1339
1340
node .is_star = True
1340
1341
return self .set_line (node , n )
@@ -1469,9 +1470,7 @@ def visit_Lambda(self, n: ast3.Lambda) -> LambdaExpr:
1469
1470
body .col_offset = n .body .col_offset
1470
1471
1471
1472
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 ]))
1475
1474
self .class_and_function_stack .pop ()
1476
1475
e .set_line (n .lineno , n .col_offset ) # Overrides set_line -- can't use self.set_line
1477
1476
return e
@@ -1743,7 +1742,7 @@ def visit_Match(self, n: Match) -> MatchStmt:
1743
1742
self .visit (n .subject ),
1744
1743
[self .visit (c .pattern ) for c in n .cases ],
1745
1744
[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 ],
1747
1746
)
1748
1747
return self .set_line (node , n )
1749
1748
0 commit comments