bpo-39031: Include elif keyword when producing lineno/col-offset info for if_stmt (GH-17582) (GH-17589)

When parsing an "elif" node, lineno and col_offset of the node now point to the "elif" keyword and not to its condition, making it consistent with the "if" node.

https://bugs.python.org/issue39031

Automerge-Triggered-By: @pablogsal
(cherry picked from commit 025a602af7)

Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
This commit is contained in:
Miss Islington (bot) 2019-12-13 08:21:54 -08:00 committed by Pablo Galindo
parent b738237d67
commit 3b18b17efc
3 changed files with 13 additions and 2 deletions

View File

@ -68,6 +68,8 @@ exec_tests = [
"while v:pass", "while v:pass",
# If # If
"if v:pass", "if v:pass",
# If-Elif
"if a:\n pass\nelif b:\n pass",
# With # With
"with x as y: pass", "with x as y: pass",
"with x as y, z as q: pass", "with x as y, z as q: pass",
@ -799,6 +801,12 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(node.body[2].col_offset, 0) self.assertEqual(node.body[2].col_offset, 0)
self.assertEqual(node.body[2].lineno, 13) self.assertEqual(node.body[2].lineno, 13)
def test_elif_stmt_start_position(self):
node = ast.parse('if a:\n pass\nelif b:\n pass\n')
elif_stmt = node.body[0].orelse[0]
self.assertEqual(elif_stmt.lineno, 3)
self.assertEqual(elif_stmt.col_offset, 0)
def test_literal_eval(self): def test_literal_eval(self):
self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3]) self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3])
self.assertEqual(ast.literal_eval('{"foo": 42}'), {"foo": 42}) self.assertEqual(ast.literal_eval('{"foo": 42}'), {"foo": 42})
@ -1781,6 +1789,7 @@ exec_results = [
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [], None)], []), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [], None)], []),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], []), ('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], []),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], []), ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], []),
('Module', [('If', (1, 0), ('Name', (1, 3), 'a', ('Load',)), [('Pass', (2, 2))], [('If', (3, 0), ('Name', (3, 5), 'b', ('Load',)), [('Pass', (4, 2))], [])])], []),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))], None)], []), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))], None)], []),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))], None)], []), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))], None)], []),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Constant', (1, 16), 'string', None)], []), None)], []), ('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Constant', (1, 16), 'string', None)], []), None)], []),

View File

@ -0,0 +1,2 @@
When parsing an "elif" node, lineno and col_offset of the node now point to the "elif" keyword and not to its condition, making it consistent with the "if" node.
Patch by Lysandros Nikolaou.

View File

@ -4079,8 +4079,8 @@ ast_for_if_stmt(struct compiling *c, const node *n)
} }
asdl_seq_SET(newobj, 0, asdl_seq_SET(newobj, 0,
If(expression, suite_seq, orelse, If(expression, suite_seq, orelse,
LINENO(CHILD(n, off)), LINENO(CHILD(n, off - 1)),
CHILD(n, off)->n_col_offset, CHILD(n, off - 1)->n_col_offset,
end_lineno, end_col_offset, c->c_arena)); end_lineno, end_col_offset, c->c_arena));
orelse = newobj; orelse = newobj;
} }