aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2019-01-22 16:00:10 +0100
committerDaniel Mensinger <daniel@mensinger-ka.de>2019-01-22 16:41:25 +0100
commitb7c6f3ec72c831c2af20eb5320d5f51b52d79227 (patch)
treec7d77532371251aefcdbe45cfb74113337340375 /mesonbuild
parente089eb7665ca9dfb28e740829652add666f4a2f0 (diff)
downloadmeson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.zip
meson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.tar.gz
meson-b7c6f3ec72c831c2af20eb5320d5f51b52d79227.tar.bz2
Can now rewrite files
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/ast/printer.py16
-rw-r--r--mesonbuild/rewriter.py86
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