mirror of https://github.com/python/cpython
GH-93662: Make sure that column offsets are correct in multi-line method calls. (GH-93673)
This commit is contained in:
parent
4caf5c2753
commit
2bf74753c1
|
@ -574,6 +574,15 @@ def positions_from_location_table(code):
|
||||||
for _ in range(length):
|
for _ in range(length):
|
||||||
yield (line, end_line, col, end_col)
|
yield (line, end_line, col, end_col)
|
||||||
|
|
||||||
|
def dedup(lst, prev=object()):
|
||||||
|
for item in lst:
|
||||||
|
if item != prev:
|
||||||
|
yield item
|
||||||
|
prev = item
|
||||||
|
|
||||||
|
def lines_from_postions(positions):
|
||||||
|
return dedup(l for (l, _, _, _) in positions)
|
||||||
|
|
||||||
def misshappen():
|
def misshappen():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -606,6 +615,13 @@ def misshappen():
|
||||||
|
|
||||||
) else p
|
) else p
|
||||||
|
|
||||||
|
def bug93662():
|
||||||
|
example_report_generation_message= (
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
).strip()
|
||||||
|
raise ValueError()
|
||||||
|
|
||||||
|
|
||||||
class CodeLocationTest(unittest.TestCase):
|
class CodeLocationTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -616,10 +632,23 @@ class CodeLocationTest(unittest.TestCase):
|
||||||
self.assertEqual(l1, l2)
|
self.assertEqual(l1, l2)
|
||||||
self.assertEqual(len(pos1), len(pos2))
|
self.assertEqual(len(pos1), len(pos2))
|
||||||
|
|
||||||
|
|
||||||
def test_positions(self):
|
def test_positions(self):
|
||||||
self.check_positions(parse_location_table)
|
self.check_positions(parse_location_table)
|
||||||
self.check_positions(misshappen)
|
self.check_positions(misshappen)
|
||||||
|
self.check_positions(bug93662)
|
||||||
|
|
||||||
|
def check_lines(self, func):
|
||||||
|
co = func.__code__
|
||||||
|
lines1 = list(dedup(l for (_, _, l) in co.co_lines()))
|
||||||
|
lines2 = list(lines_from_postions(positions_from_location_table(co)))
|
||||||
|
for l1, l2 in zip(lines1, lines2):
|
||||||
|
self.assertEqual(l1, l2)
|
||||||
|
self.assertEqual(len(lines1), len(lines2))
|
||||||
|
|
||||||
|
def test_lines(self):
|
||||||
|
self.check_lines(parse_location_table)
|
||||||
|
self.check_lines(misshappen)
|
||||||
|
self.check_lines(bug93662)
|
||||||
|
|
||||||
|
|
||||||
if check_impl_detail(cpython=True) and ctypes is not None:
|
if check_impl_detail(cpython=True) and ctypes is not None:
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Make sure that the end column offsets are correct in multi-line method
|
||||||
|
calls. Previously, the end column could precede the column offset.
|
|
@ -4801,6 +4801,16 @@ is_import_originated(struct compiler *c, expr_ty e)
|
||||||
return flags & DEF_IMPORT;
|
return flags & DEF_IMPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_location_to_match_attr(struct compiler *c, expr_ty meth)
|
||||||
|
{
|
||||||
|
if (meth->lineno != meth->end_lineno) {
|
||||||
|
// Make start location match attribute
|
||||||
|
c->u->u_lineno = meth->end_lineno;
|
||||||
|
c->u->u_col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return 1 if the method call was optimized, -1 if not, and 0 on error.
|
// Return 1 if the method call was optimized, -1 if not, and 0 on error.
|
||||||
static int
|
static int
|
||||||
maybe_optimize_method_call(struct compiler *c, expr_ty e)
|
maybe_optimize_method_call(struct compiler *c, expr_ty e)
|
||||||
|
@ -4842,8 +4852,8 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
|
||||||
}
|
}
|
||||||
/* Alright, we can optimize the code. */
|
/* Alright, we can optimize the code. */
|
||||||
VISIT(c, expr, meth->v.Attribute.value);
|
VISIT(c, expr, meth->v.Attribute.value);
|
||||||
int old_lineno = c->u->u_lineno;
|
SET_LOC(c, meth);
|
||||||
c->u->u_lineno = meth->end_lineno;
|
update_location_to_match_attr(c, meth);
|
||||||
ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names);
|
ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names);
|
||||||
VISIT_SEQ(c, expr, e->v.Call.args);
|
VISIT_SEQ(c, expr, e->v.Call.args);
|
||||||
|
|
||||||
|
@ -4853,8 +4863,9 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
SET_LOC(c, e);
|
||||||
|
update_location_to_match_attr(c, meth);
|
||||||
ADDOP_I(c, CALL, argsl + kwdsl);
|
ADDOP_I(c, CALL, argsl + kwdsl);
|
||||||
c->u->u_lineno = old_lineno;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7673,6 +7684,7 @@ write_location_info_short_form(struct assembler* a, int length, int column, int
|
||||||
int column_low_bits = column & 7;
|
int column_low_bits = column & 7;
|
||||||
int column_group = column >> 3;
|
int column_group = column >> 3;
|
||||||
assert(column < 80);
|
assert(column < 80);
|
||||||
|
assert(end_column >= column);
|
||||||
assert(end_column - column < 16);
|
assert(end_column - column < 16);
|
||||||
write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
|
write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
|
||||||
write_location_byte(a, (column_low_bits << 4) | (end_column - column));
|
write_location_byte(a, (column_low_bits << 4) | (end_column - column));
|
||||||
|
@ -7744,7 +7756,7 @@ write_location_info_entry(struct assembler* a, struct instr* i, int isize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i->i_end_lineno == i->i_lineno) {
|
else if (i->i_end_lineno == i->i_lineno) {
|
||||||
if (line_delta == 0 && column < 80 && end_column - column < 16) {
|
if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
|
||||||
write_location_info_short_form(a, isize, column, end_column);
|
write_location_info_short_form(a, isize, column, end_column);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue