Skip to content

Commit

Permalink
pythonGH-93662: Make sure that column offsets are correct in multi-li…
Browse files Browse the repository at this point in the history
…ne method calls. (pythonGH-93673)
  • Loading branch information
markshannon authored and iritkatriel committed Jun 16, 2022
1 parent 6e28032 commit 483f3d0
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
31 changes: 30 additions & 1 deletion Lib/test/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,15 @@ def positions_from_location_table(code):
for _ in range(length):
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():
"""
Expand Down Expand Up @@ -606,6 +615,13 @@ def misshappen():

) else p

def bug93662():
example_report_generation_message= (
"""
"""
).strip()
raise ValueError()


class CodeLocationTest(unittest.TestCase):

Expand All @@ -616,10 +632,23 @@ def check_positions(self, func):
self.assertEqual(l1, l2)
self.assertEqual(len(pos1), len(pos2))


def test_positions(self):
self.check_positions(parse_location_table)
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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
20 changes: 16 additions & 4 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4780,6 +4780,16 @@ is_import_originated(struct compiler *c, expr_ty e)
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.
static int
maybe_optimize_method_call(struct compiler *c, expr_ty e)
Expand Down Expand Up @@ -4821,8 +4831,8 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
}
/* Alright, we can optimize the code. */
VISIT(c, expr, meth->v.Attribute.value);
int old_lineno = c->u->u_lineno;
c->u->u_lineno = meth->end_lineno;
SET_LOC(c, meth);
update_location_to_match_attr(c, meth);
ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names);
VISIT_SEQ(c, expr, e->v.Call.args);

Expand All @@ -4832,9 +4842,10 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
return 0;
};
}
SET_LOC(c, e);
update_location_to_match_attr(c, meth);
ADDOP_I(c, PRECALL, argsl + kwdsl);
ADDOP_I(c, CALL, argsl + kwdsl);
c->u->u_lineno = old_lineno;
return 1;
}

Expand Down Expand Up @@ -7508,6 +7519,7 @@ write_location_info_short_form(struct assembler* a, int length, int column, int
int column_low_bits = column & 7;
int column_group = column >> 3;
assert(column < 80);
assert(end_column >= column);
assert(end_column - column < 16);
write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
write_location_byte(a, (column_low_bits << 4) | (end_column - column));
Expand Down Expand Up @@ -7579,7 +7591,7 @@ write_location_info_entry(struct assembler* a, struct instr* i, int isize)
}
}
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);
return 1;
}
Expand Down

0 comments on commit 483f3d0

Please sign in to comment.