rewriter: Added support for removing targets

pull/4929/head
Daniel Mensinger 6 years ago
parent 24a2cf02e2
commit 056c533ede
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 53
      mesonbuild/rewriter.py
  2. 26
      run_unittests.py
  3. 2
      test cases/rewrite/1 basic/meson.build
  4. 12
      test cases/rewrite/1 basic/rmTgt.json
  5. 7
      test cases/rewrite/2 subdirs/rmTgt.json

@ -251,8 +251,9 @@ rewriter_keys = {
},
'target': {
'target': (str, None, None),
'operation': (str, None, ['src_add', 'src_rm', 'info']),
'operation': (str, None, ['src_add', 'src_rm', 'tgt_rm', 'info']),
'sources': (list, [], None),
'subdir': (str, '', None),
'debug': (bool, False, None)
}
}
@ -547,6 +548,14 @@ class Rewriter:
if root not in self.modefied_nodes:
self.modefied_nodes += [root]
elif cmd['operation'] == 'tgt_rm':
to_remove = self.find_assignment_node(target['node'])
if to_remove is None:
to_remove = target['node']
self.to_remove_nodes += [to_remove]
mlog.log(' -- Removing target', mlog.green(cmd['target']), 'at',
mlog.yellow('{}:{}'.format(os.path.join(to_remove.subdir, environment.build_filename), to_remove.lineno)))
elif cmd['operation'] == 'info':
# List all sources in the target
src_list = []
@ -570,20 +579,28 @@ class Rewriter:
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(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'subdir') for x in self.to_remove_nodes))
assert(all(isinstance(x, (mparser.ArrayNode, mparser.FunctionNode)) for x in self.modefied_nodes))
assert(all(isinstance(x, (mparser.ArrayNode, mparser.AssignmentNode, mparser.FunctionNode)) for x in self.to_remove_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))
work_nodes = [{'node': x, 'action': 'modify'} for x in self.modefied_nodes]
work_nodes += [{'node': x, 'action': 'rm'} for x in self.to_remove_nodes]
work_nodes = list(sorted(work_nodes, key=lambda x: x['node'].lineno * 1000 + x['node'].colno, reverse=True))
# Generating the new replacement string
str_list = []
for i in work_nodes:
printer = AstPrinter()
i.accept(printer)
printer.post_process()
new_data = ''
if i['action'] == 'modify':
printer = AstPrinter()
i['node'].accept(printer)
printer.post_process()
new_data = printer.result.strip()
data = {
'file': os.path.join(i.subdir, environment.build_filename),
'str': printer.result.strip(),
'node': i
'file': os.path.join(i['node'].subdir, environment.build_filename),
'str': new_data,
'node': i['node'],
'action': i['action']
}
str_list += [data]
@ -612,7 +629,7 @@ class Rewriter:
}
# Replace in source code
for i in str_list:
def remove_node(i):
offsets = files[i['file']]['offsets']
raw = files[i['file']]['raw']
node = i['node']
@ -623,7 +640,7 @@ class Rewriter:
if isinstance(node, mparser.ArrayNode):
if raw[end] != '[':
mlog.warning('Internal error: expected "[" at {}:{} but got "{}"'.format(line, col, raw[end]))
continue
return
counter = 1
while counter > 0:
end += 1
@ -632,6 +649,7 @@ class Rewriter:
elif raw[end] == ']':
counter -= 1
end += 1
elif isinstance(node, mparser.FunctionNode):
while raw[end] != '(':
end += 1
@ -644,8 +662,23 @@ class Rewriter:
elif raw[end] == ')':
counter -= 1
end += 1
# Only removal is supported for assignments
elif isinstance(node, mparser.AssignmentNode) and i['action'] == 'rm':
if isinstance(node.value, (mparser.ArrayNode, mparser.FunctionNode)):
remove_node({'file': i['file'], 'str': '', 'node': node.value, 'action': 'rm'})
raw = files[i['file']]['raw']
while raw[end] != '=':
end += 1
end += 1 # Handle the '='
while raw[end] in [' ', '\n', '\t']:
end += 1
raw = files[i['file']]['raw'] = raw[:start] + i['str'] + raw[end:]
for i in str_list:
remove_node(i)
# Write the files back
for key, val in files.items():
mlog.log('Rewriting', mlog.yellow(key))

@ -5161,6 +5161,32 @@ class RewriterTests(BasePlatformTests):
out = self.extract_test_data(out)
self.assertDictEqual(list(out['target'].values())[0], expected)
def test_target_remove(self):
self.prime('1 basic')
self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json'))
out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json'))
out = self.extract_test_data(out)
expected = {
'target': {
'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp']},
'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp']},
'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp']},
'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp']},
'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp']},
'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp']},
'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp']},
}
}
self.assertDictEqual(out, expected)
def test_target_remove_subdir(self):
self.prime('2 subdirs')
self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json'))
out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json'))
out = self.extract_test_data(out)
self.assertDictEqual(out, {})
def test_kwargs_info(self):
self.prime('3 kwargs')
out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json'))

@ -15,4 +15,4 @@ exe5 = executable('trivialprog5', [src2, 'main.cpp'])
exe6 = executable('trivialprog6', 'main.cpp', 'fileA.cpp')
exe7 = executable('trivialprog7', 'fileB.cpp', src1, 'fileC.cpp')
exe8 = executable('trivialprog8', src3)
exe9 = executable('trivialprog9', src4)
executable('trivialprog9', src4)

@ -0,0 +1,12 @@
[
{
"type": "target",
"target": "trivialprog1",
"operation": "tgt_rm"
},
{
"type": "target",
"target": "trivialprog9",
"operation": "tgt_rm"
}
]

@ -0,0 +1,7 @@
[
{
"type": "target",
"target": "something",
"operation": "tgt_rm"
}
]
Loading…
Cancel
Save