mintro: Fix resolving nodes in kwargs (fixes #5884)

pull/5891/head
Daniel Mensinger 5 years ago committed by Dylan Baker
parent 51a601c2ee
commit bd37147b4b
  1. 108
      mesonbuild/ast/interpreter.py
  2. 4
      test cases/unit/59 introspect buildoptions/meson.build

@ -245,7 +245,7 @@ class AstInterpreter(interpreterbase.InterpreterBase):
self.reverse_assignment[node.value.ast_id] = node
self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case
def flatten_args(self, args: Any, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> List[str]:
def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> Optional[Any]:
def quick_resolve(n: BaseNode, loop_detect: Optional[List[str]] = None) -> Any:
if loop_detect is None:
loop_detect = []
@ -260,74 +260,98 @@ class AstInterpreter(interpreterbase.InterpreterBase):
if id_loop_detect is None:
id_loop_detect = []
flattend_args = []
result = None
if not isinstance(node, BaseNode):
return None
assert(hasattr(node, 'ast_id'))
if node.ast_id in id_loop_detect:
return None # Loop detected
id_loop_detect += [node.ast_id]
if isinstance(args, BaseNode):
assert(hasattr(args, 'ast_id'))
if args.ast_id in id_loop_detect:
return [] # Loop detected
id_loop_detect += [args.ast_id]
# Try to evealuate the value of the node
if isinstance(node, IdNode):
result = quick_resolve(node)
if isinstance(args, ArrayNode):
args = [x for x in args.args.arguments]
elif isinstance(node, ElementaryNode):
result = node.value
elif isinstance(args, ArgumentNode):
args = [x for x in args.arguments]
elif isinstance(node, ArrayNode):
result = [x for x in node.args.arguments]
elif isinstance(args, ArithmeticNode):
if args.operation != 'add':
return [] # Only handle string and array concats
l = quick_resolve(args.left)
r = quick_resolve(args.right)
elif isinstance(node, ArgumentNode):
result = [x for x in node.arguments]
elif isinstance(node, ArithmeticNode):
if node.operation != 'add':
return None # Only handle string and array concats
l = quick_resolve(node.left)
r = quick_resolve(node.right)
if isinstance(l, str) and isinstance(r, str):
args = [l + r] # String concatination detected
result = l + r # String concatination detected
else:
args = self.flatten_args(l, include_unknown_args, id_loop_detect) + self.flatten_args(r, include_unknown_args, id_loop_detect)
result = self.flatten_args(l, include_unknown_args, id_loop_detect) + self.flatten_args(r, include_unknown_args, id_loop_detect)
elif isinstance(args, MethodNode):
src = quick_resolve(args.source_object)
margs = self.flatten_args(args.args, include_unknown_args, id_loop_detect)
elif isinstance(node, MethodNode):
src = quick_resolve(node.source_object)
margs = self.flatten_args(node.args, include_unknown_args, id_loop_detect)
try:
if isinstance(src, str):
args = [self.string_method_call(src, args.name, margs)]
result = self.string_method_call(src, node.name, margs)
elif isinstance(src, bool):
args = [self.bool_method_call(src, args.name, margs)]
result = self.bool_method_call(src, node.name, margs)
elif isinstance(src, int):
args = [self.int_method_call(src, args.name, margs)]
result = self.int_method_call(src, node.name, margs)
elif isinstance(src, list):
args = [self.array_method_call(src, args.name, margs)]
result = self.array_method_call(src, node.name, margs)
elif isinstance(src, dict):
args = [self.dict_method_call(src, args.name, margs)]
else:
return []
result = self.dict_method_call(src, node.name, margs)
except mesonlib.MesonException:
return []
return None
# Ensure that the result is fully resolved (no more nodes)
if isinstance(result, BaseNode):
result = self.resolve_node(result, include_unknown_args, id_loop_detect)
elif isinstance(result, list):
new_res = []
for i in result:
if isinstance(i, BaseNode):
resolved = self.resolve_node(i, include_unknown_args, id_loop_detect)
if resolved is not None:
new_res += self.flatten_args(resolved, include_unknown_args, id_loop_detect)
else:
new_res += [i]
result = new_res
return result
def flatten_args(self, args: Any, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> List[Any]:
# Make sure we are always dealing with lists
if not isinstance(args, list):
args = [args]
flattend_args = []
# Resolve the contents of args
for i in args:
if isinstance(i, IdNode):
flattend_args += self.flatten_args(quick_resolve(i), include_unknown_args, id_loop_detect)
elif isinstance(i, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
flattend_args += self.flatten_args(i, include_unknown_args, id_loop_detect)
elif isinstance(i, mparser.ElementaryNode):
flattend_args += [i.value]
elif isinstance(i, (str, bool, int, float)):
flattend_args += [i]
elif include_unknown_args:
if isinstance(i, BaseNode):
resolved = self.resolve_node(i, include_unknown_args, id_loop_detect)
if resolved is not None:
if not isinstance(resolved, list):
resolved = [resolved]
flattend_args += resolved
elif isinstance(i, (str, bool, int, float)) or include_unknown_args:
flattend_args += [i]
return flattend_args
def flatten_kwargs(self, kwargs: object, include_unknown_args: bool = False):
flattend_kwargs = {}
for key, val in kwargs.items():
if isinstance(val, ElementaryNode):
flattend_kwargs[key] = val.value
elif isinstance(val, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
flattend_kwargs[key] = self.flatten_args(val, include_unknown_args)
if isinstance(val, BaseNode):
resolved = self.resolve_node(val, include_unknown_args)
if resolved is not None:
flattend_kwargs[key] = resolved
elif isinstance(val, (str, bool, int, float)) or include_unknown_args:
flattend_kwargs[key] = val
return flattend_kwargs

@ -5,7 +5,9 @@ subA = subproject('projectA')
target_name = 'MAIN'
target_src = ['main.c']
executable(target_name, target_src)
foo = false
executable(target_name, target_src, build_by_default : foo)
r = run_command(find_program('c_compiler.py'))
if r.returncode() != 0

Loading…
Cancel
Save