diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-01-31 13:55:20 +0100 |
---|---|---|
committer | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-01-31 15:43:04 +0100 |
commit | be3c58d6388c845fdde4374258dbb4ffbe18c5ca (patch) | |
tree | 6cd2ecb97433bb644db64e1e222c90c59dcdc3e2 | |
parent | 8224ecfbe6e1811680113740341a277407904eb9 (diff) | |
download | meson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.zip meson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.tar.gz meson-be3c58d6388c845fdde4374258dbb4ffbe18c5ca.tar.bz2 |
Modify kwargs in rewriter
-rw-r--r-- | mesonbuild/rewriter.py | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 3426896..de39f63 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -71,7 +71,184 @@ class RequiredKeys: return wrapped +class MesonBaseType: + def __init__(self, node: mparser.BaseNode): + if node is None: + self.node = self._new_node() + else: + self.node = node + self.node_type = None + for i in self.supported_nodes(): + if isinstance(self.node, i): + self.node_type = i + + def _new_node(self): + # Overwrite in derived class + return mparser.BaseNode() + + def can_modify(self): + return self.node_type is not None + + def get_node(self): + return self.node + + def supported_nodes(self): + # Overwrite in derived class + return [] + + def set_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping') + + def add_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping') + + def remove_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot remove a value of type', mlog.bold(type(self).__name__), '--> skipping') + +class MesonStr(MesonBaseType): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_node(self): + return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, '')) + + def supported_nodes(self): + return [mparser.StringNode] + + def set_value(self, value): + self.node.value = str(value) + +class MesonBool(MesonBaseType): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_node(self): + return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, False)) + + def supported_nodes(self): + return [mparser.BooleanNode] + + def set_value(self, value): + self.node.value = bool(value) + +class MesonID(MesonBaseType): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_node(self): + return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, '')) + + def supported_nodes(self): + return [mparser.IdNode] + + def set_value(self, value): + self.node.value = str(value) + +class MesonList(MesonBaseType): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_node(self): + return mparser.ArrayNode(mparser.ArgumentNode(mparser.Token('', '', 0, 0, 0, None, '')), 0, 0) + + def _new_element_node(self, value): + # Overwrite in derived class + return mparser.BaseNode() + + def _ensure_array_node(self): + if not isinstance(self.node, mparser.ArrayNode): + tmp = self.node + self.node = self._new_node() + self.node.args.arguments += [tmp] + + def _check_is_equal(self, node, value): + # Overwrite in derived class + return False + + def get_node(self): + if isinstance(self.node, mparser.ArrayNode): + if len(self.node.args.arguments) == 1: + return self.node.args.arguments[0] + return self.node + + def supported_element_nodes(self): + # Overwrite in derived class + return [] + + def supported_nodes(self): + return [mparser.ArrayNode] + self.supported_element_nodes() + + def set_value(self, value): + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + self.node.args.arguments = [] # Remove all current nodes + for i in value: + self.node.args.arguments += [self._new_element_node(i)] + + def add_value(self, value): + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + for i in value: + self.node.args.arguments += [self._new_element_node(i)] + + def remove_value(self, value): + def check_remove_node(node): + for j in value: + if self._check_is_equal(i, j): + return True + return False + + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + removed_list = [] + for i in self.node.args.arguments: + if not check_remove_node(i): + removed_list += [i] + self.node.args.arguments = removed_list + +class MesonStrList(MesonList): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_element_node(self, value): + return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, str(value))) + + def _check_is_equal(self, node, value): + if isinstance(node, mparser.StringNode): + return node.value == value + return False + + def supported_element_nodes(self): + return [mparser.StringNode] + +class MesonIDList(MesonList): + def __init__(self, node: mparser.BaseNode): + super().__init__(node) + + def _new_element_node(self, value): + return mparser.StringNode(mparser.Token('', '', 0, 0, 0, None, str(value))) + + def _check_is_equal(self, node, value): + if isinstance(node, mparser.IdNode): + return node.value == value + return False + + def supported_element_nodes(self): + return [mparser.IdNode] + rewriter_keys = { + 'kwargs': { + 'function': (str, None, None), + 'id': (str, None, None), + 'operation': (str, None, ['set', 'delete', 'add', 'remove']), + 'kwargs': (dict, {}, None) + }, 'target': { 'target': (str, None, None), 'operation': (str, None, ['src_add', 'src_rm', 'test']), @@ -80,6 +257,38 @@ rewriter_keys = { } } +rewriter_func_kwargs = { + 'dependency': { + 'language': MesonStr, + 'method': MesonStr, + 'native': MesonBool, + 'not_found_message': MesonStr, + 'required': MesonBool, + 'static': MesonBool, + 'version': MesonStrList, + 'modules': MesonStrList + }, + 'target': { + 'build_by_default': MesonBool, + 'build_rpath': MesonStr, + 'dependencies': MesonIDList, + 'gui_app': MesonBool, + 'link_with': MesonIDList, + 'export_dynamic': MesonBool, + 'implib': MesonBool, + 'install': MesonBool, + 'install_dir': MesonStr, + 'install_rpath': MesonStr, + 'pie': MesonBool + }, + 'project': { + 'meson_version': MesonStr, + 'license': MesonStrList, + 'subproject_dir': MesonStr, + 'version': MesonStr + } +} + class Rewriter: def __init__(self, sourcedir: str, generator: str = 'ninja'): self.sourcedir = sourcedir @@ -87,6 +296,7 @@ class Rewriter: self.id_generator = AstIDGenerator() self.modefied_nodes = [] self.functions = { + 'kwargs': self.process_kwargs, 'target': self.process_target, } @@ -120,6 +330,67 @@ class Rewriter: return tgt + @RequiredKeys(rewriter_keys['kwargs']) + def process_kwargs(self, cmd): + mlog.log('Processing function type', mlog.bold(cmd['function']), 'with id', mlog.cyan("'" + cmd['id'] + "'")) + if cmd['function'] not in rewriter_func_kwargs: + mlog.error('Unknown function type {} --> skipping'.format(cmd['function'])) + return + kwargs_def = rewriter_func_kwargs[cmd['function']] + + # Find the function node to modify + node = None + if cmd['function'] == 'project': + node = self.interpreter.project_node + elif cmd['function'] == 'target': + tmp = self.find_target(cmd['id']) + if tmp: + node = tmp['node'] + if not node: + mlog.error('Unable to find the function node') + assert(isinstance(node, mparser.FunctionNode)) + + num_changed = 0 + for key, val in cmd['kwargs'].items(): + if key not in kwargs_def: + mlog.error('Cannot modify unknown kwarg --> skipping', mlog.bold(key)) + continue + + # Remove the key from the kwargs + if cmd['operation'] == 'delete': + if key in node.args.kwargs: + mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') + del node.args.kwargs[key] + num_changed += 1 + else: + mlog.log(' -- Key', mlog.bold(key), 'is already deleted') + continue + + if key not in node.args.kwargs: + node.args.kwargs[key] = None + modifyer = kwargs_def[key](node.args.kwargs[key]) + if not modifyer.can_modify(): + mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify') + + # Apply the operation + val_str = str(val) + if cmd['operation'] == 'set': + mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str)) + modifyer.set_value(val) + elif cmd['operation'] == 'add': + mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) + modifyer.add_value(val) + elif cmd['operation'] == 'remove': + mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifyer.remove_value(val) + + # Write back the result + node.args.kwargs[key] = modifyer.get_node() + num_changed += 1 + + if num_changed > 0 and node not in self.modefied_nodes: + self.modefied_nodes += [node] + @RequiredKeys(rewriter_keys['target']) def process_target(self, cmd): mlog.log('Processing target', mlog.bold(cmd['target']), 'operation', mlog.cyan(cmd['operation'])) |