diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-01-22 16:00:10 +0100 |
---|---|---|
committer | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-01-22 16:41:25 +0100 |
commit | b7c6f3ec72c831c2af20eb5320d5f51b52d79227 (patch) | |
tree | c7d77532371251aefcdbe45cfb74113337340375 /mesonbuild | |
parent | e089eb7665ca9dfb28e740829652add666f4a2f0 (diff) | |
download | meson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.zip meson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.tar.gz meson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.tar.bz2 |
Can now rewrite files
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/ast/printer.py | 16 | ||||
-rw-r--r-- | mesonbuild/rewriter.py | 86 |
2 files changed, 100 insertions, 2 deletions
diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index aab5a30..1f58146 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -17,6 +17,7 @@ from .. import mparser from . import AstVisitor +import re arithmic_map = { 'add': '+', @@ -33,11 +34,18 @@ class AstPrinter(AstVisitor): self.arg_newline_cutoff = arg_newline_cutoff self.ci = '' self.is_newline = True + self.last_level = 0 + + def post_process(self): + self.result = re.sub(r'\s+\n', '\n', self.result) def append(self, data: str, node: mparser.BaseNode): level = 0 if node and hasattr(node, 'level'): level = node.level + else: + level = self.last_level + self.last_level = level if self.is_newline: self.result += ' ' * (level * self.indent) self.result += data @@ -179,13 +187,17 @@ class AstPrinter(AstVisitor): self.newline() for i in node.arguments: i.accept(self) - self.append(',', node) + self.append(', ', node) if break_args: self.newline() for key, val in node.kwargs.items(): self.append(key, node) self.appendS(':', node) val.accept(self) - self.append(',', node) + self.append(', ', node) if break_args: self.newline() + if break_args: + self.result = re.sub(r', \n$', '\n', self.result) + else: + self.result = re.sub(r', $', '', self.result) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 6a11767..dfed1c6 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -219,6 +219,90 @@ class Rewriter: .format(cmd['type'], list(self.functions.keys()))) self.functions[cmd['type']](cmd) + def apply_changes(self): + assert(all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'subdir') for x in self.modefied_nodes)) + assert(all(isinstance(x, (mparser.ArrayNode, mparser.FunctionNode)) for x in self.modefied_nodes)) + # Sort based on line and column in reversed order + work_nodes = list(sorted(self.modefied_nodes, key=lambda x: x.lineno * 1000 + x.colno, reverse=True)) + + # Generating the new replacement string + str_list = [] + for i in work_nodes: + printer = AstPrinter() + i.accept(printer) + printer.post_process() + data = { + 'file': os.path.join(i.subdir, environment.build_filename), + 'str': printer.result.strip(), + 'node': i + } + str_list += [data] + + # Load build files + files = {} + for i in str_list: + if i['file'] in files: + continue + fpath = os.path.realpath(os.path.join(self.sourcedir, i['file'])) + fdata = '' + with open(fpath, 'r') as fp: + fdata = fp.read() + + # Generate line offsets numbers + m_lines = fdata.splitlines(True) + offset = 0 + line_offsets = [] + for j in m_lines: + line_offsets += [offset] + offset += len(j) + + files[i['file']] = { + 'path': fpath, + 'raw': fdata, + 'offsets': line_offsets + } + + # Replace in source code + for i in str_list: + offsets = files[i['file']]['offsets'] + raw = files[i['file']]['raw'] + node = i['node'] + line = node.lineno - 1 + col = node.colno + start = offsets[line]+col + end = start + if isinstance(node, mparser.ArrayNode): + if raw[end] != '[': + mlog.warning('Internal error: expected "[" at {}:{} but got "{}"'.format(line, col, raw[end])) + continue + counter = 1 + while counter > 0: + end += 1 + if raw[end] == '[': + counter += 1 + elif raw[end] == ']': + counter -= 1 + end += 1 + elif isinstance(node, mparser.FunctionNode): + while raw[end] != '(': + end += 1 + end += 1 + counter = 1 + while counter > 0: + end += 1 + if raw[end] == '(': + counter += 1 + elif raw[end] == ')': + counter -= 1 + end += 1 + raw = files[i['file']]['raw'] = raw[:start] + i['str'] + raw[end:] + + # Write the files back + for key, val in files.items(): + mlog.log('Rewriting', mlog.yellow(key)) + with open(val['path'], 'w') as fp: + fp.write(val['raw']) + def run(options): rewriter = Rewriter(options.sourcedir) rewriter.analyze_meson() @@ -235,4 +319,6 @@ def run(options): if not isinstance(i, object): raise TypeError('Command is not an object') rewriter.process(i) + + rewriter.apply_changes() return 0 |