lexer: Pass the column in to py_compile.

This commit is contained in:
Tom Rothamel
2025-02-17 01:15:15 -05:00
parent 149d16b1ec
commit 2cda751596
3 changed files with 79 additions and 24 deletions
+2 -1
View File
@@ -47,8 +47,9 @@ class PyExpr(str):
linenumber: int
py: int
hashcode: int
column: int
def __new__(cls, s: str, filename: str, linenumber: int, py: int = 3, hashcode: int | None = None, /) -> PyExpr:
def __new__(cls, s: str, filename: str, linenumber: int, py: int = 3, hashcode: int | None = None, column: int = 0, /) -> PyExpr:
...
@staticmethod
+76 -22
View File
@@ -854,33 +854,79 @@ py_compile_cache = { }
# An old version of the same, that's preserved across reloads.
old_py_compile_cache = { }
LocatableNode = ast.stmt|ast.expr
def fix_locations(node, lineno, col_offset):
class LocationFixer:
"""
Assigns locations to the given node, and all of its children, adding
any missing line numbers and column offsets.
This class is responsible for fixing the locations of nodes in the AST. First,
it will adjust the line numbers and column offsets, and then it will use this
information to fill in missing attributes.
`line_delta`
The number of lines to add to the line numbers of the nodes.
`first_line_col_delta`
The number of columns to add to the column offsets of the first line.
`rest_line_col_delta`
The number of columns to add to the column offsets of the rest of the lines.
"""
start = max(
(lineno, col_offset),
(getattr(node, "lineno", None) or 1, getattr(node, "col_offset", None) or 0)
)
line_delta: int
first_line_col_delta: int
rest_line_col_delta: int
lineno, col_offset = start
def __init__(self, node: ast.stmt|ast.expr, line_delta: int=0, first_line_col_delta: int=0, rest_line_col_delta: int=0):
self.line_delta = line_delta
self.first_line_col_delta = first_line_col_delta
self.rest_line_col_delta = rest_line_col_delta
node.lineno = lineno
node.col_offset = col_offset
self.fix(node, 1 + line_delta, first_line_col_delta)
ends = [ start, (getattr(node, "end_lineno", None) or 1, getattr(node, "end_col_offset", None) or 0) ]
def fix(self, node: ast.stmt|ast.expr, lineno=1, col_offset=0):
for child in ast.iter_child_nodes(node):
fix_locations(child, lineno, col_offset)
ends.append((child.end_lineno, child.end_col_offset))
# This finds missing attributes by triggering AttributeErrors if an attribute is missing.
try:
if node.lineno == 1:
node.col_offset += self.first_line_col_delta
else:
node.col_offset += self.rest_line_col_delta
end = max(ends)
node.lineno += self.line_delta
node.end_lineno = end[0]
node.end_col_offset = end[1]
except (AttributeError, TypeError):
node.lineno = 1 + self.line_delta
node.col_offset = self.first_line_col_delta
try:
if node.end_lineno == 1:
node.end_col_offset += self.first_line_col_delta
else:
node.end_col_offset += self.rest_line_col_delta
node.end_lineno += self.line_delta
except (AttributeError, TypeError):
node.end_lineno = node.lineno
node.end_col_offset = node.col_offset
start = max(
(lineno, col_offset),
(node.lineno, node.col_offset)
)
lineno, col_offset = start
node.lineno = lineno
node.col_offset = col_offset
ends = [ start, (node.end_lineno, node.end_col_offset) ]
for child in ast.iter_child_nodes(node):
self.fix(child, lineno, col_offset)
ends.append((child.end_lineno, child.end_col_offset))
node.end_lineno, node.end_col_offset = max(ends)
def quote_eval(s):
@@ -973,7 +1019,7 @@ def quote_eval(s):
def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=True, py=None, hashcode=None):
def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=True, py=None, hashcode=None, column=0):
"""
Compiles the given source code using the supplied codegenerator.
Lists, List Comprehensions, and Dictionaries are wrapped when
@@ -997,10 +1043,16 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
`ast_node`
Rather than returning compiled bytecode, returns the AST object
that would be used.
`column`
A column offset to add to the column numbers of the source.
"""
global compile_warnings
first_line_column_delta = column
rest_line_column_delta = column
if ast_node:
cache = False
@@ -1012,6 +1064,9 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
lineno = source.linenumber
hashcode = source.hashcode
first_line_column_delta = source.column
rest_line_column_delta = 0
if py is None:
py = source.py
@@ -1033,7 +1088,7 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
if cache:
key = (hashcode, lineno, filename, mode, renpy.script.MAGIC, flags)
key = (hashcode, lineno, filename, mode, renpy.script.MAGIC, flags, column)
warnings_key = ("warnings", key)
rv = py_compile_cache.get(key, None)
@@ -1119,8 +1174,7 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
if mode == "hide":
wrap_hide(tree)
fix_locations(tree, 1, 0)
ast.increment_lineno(tree, lineno - 1)
LocationFixer(tree, lineno - 1, first_line_column_delta, rest_line_column_delta)
line_offset = 0
@@ -1135,7 +1189,7 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
handled = False
try:
tree = renpy.compat.fixes.fix_ast(tree)
fix_locations(tree, 1, 0)
LocationFixer(tree, 0, 0, 0)
rv = compile(tree, filename, py_mode, flags, True)
handled = True
except Exception:
+1 -1
View File
@@ -81,7 +81,7 @@ def compile_expr(loc, node):
flags = renpy.python.new_compile_flags | renpy.python.file_compiler_flags.get(filename, 0)
expr = ast.Expression(body=node)
renpy.python.fix_locations(expr, 1, 0)
renpy.python.LocationFixer(node)
return compile(expr, filename, "eval", flags, True)
class SLContext(renpy.ui.Addable):