Repository: mesonbuild/meson

Issue:
meson configure crashes with TypeError
```
Traceback (most recent call last):
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/mesonmain.py", line 129, in run
    return options.run_func(options)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/mconf.py", line 208, in run
    c = Conf(builddir)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/mconf.py", line 57, in __init__
    intr.analyze()
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/ast/introspection.py", line 277, in analyze
    self.run()
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 412, in run
    self.evaluate_codeblock(self.ast, start=1)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 436, in evaluate_codeblock
    raise e
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 430, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 441, in evaluate_statement
    return self.function_call(cur)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 778, in function_call
    return func(node, posargs, kwargs)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/ast/interpreter.py", line 163, in func_subdir
    self.evaluate_codeblock(codeblock)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 436, in evaluate_codeblock
    raise e
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 430, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 443, in evaluate_statement
    return self.assignment(cur)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/ast/interpreter.py", line 245, in assignment
    self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 441, in evaluate_statement
    return self.function_call(cur)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/interpreterbase.py", line 778, in function_call
    return func(node, posargs, kwargs)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/ast/introspection.py", line 237, in func_shared_lib
    return self.build_target(node, args, kwargs, SharedLibrary)
  File "/home/peterke/DEV/meson/venv/lib64/python3.7/site-packages/meson-0.51.999-py3.7.egg/mesonbuild/ast/introspection.py", line 165, in build_target
    srcqueue += kwargs['sources']
TypeError: 'ArithmeticNode' object is not iterable
```
Tested with c904d3eefe2a01ca60027e2a5192e1f1c7ca5d9d

---
Example meson.build on which it fails:
```
common_inc = include_directories('.')

common_cflags = ['-DG_LOG_DOMAIN="@0@"'.format(gvfs_name.to_upper())]

sources = files(
  'gmountoperationdbus.c',
  'gmountsource.c',
  'gmountspec.c',
  'gmounttracker.c',
  'gvfsdaemonprotocol.c',
  'gvfsfileinfo.c',
  'gvfsicon.c',
  'gvfsmonitorimpl.c',
  'gvfsutils.c',
)

dbus_sources = gnome.gdbus_codegen(
  'gvfsdbus',
  gvfs_namespace + '.xml',
  interface_prefix: gvfs_namespace + '.',
  namespace: 'GVfsDBus',
  autocleanup: 'objects',
)

deps = [
  gio_dep,
  glib_dep,
  gobject_dep,
]

cflags = common_cflags + ['-DREMOTE_VOLUME_MONITORS_DIR="@0@"'.format(gvfs_prefix / gvfs_remote_volume_monitors_dir)]

libgvfscommon = shared_library(
  'gvfscommon',
  sources: sources + [dbus_sources],
  include_directories: top_inc,
  dependencies: deps + [gio_unix_dep],
  c_args: cflags,
  install: true,
  install_dir: gvfs_pkglibdir,
)

libgvfscommon_dep = declare_dependency(
  sources: dbus_sources[1],
  include_directories: common_inc,
  dependencies: deps,
  link_with: libgvfscommon,
)
```
(truncated from https://gitlab.gnome.org/GNOME/gvfs/blob/master/common/meson.build)



Discussion:

Resolving patch:
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -325,7 +325,7 @@ def flatten_kwargs(self, kwargs: object, include_unknown_args: bool = False):
         for key, val in kwargs.items():
             if isinstance(val, ElementaryNode):
                 flattend_kwargs[key] = val.value
-            elif isinstance(val, (ArrayNode, ArgumentNode)):
+            elif isinstance(val, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
                 flattend_kwargs[key] = self.flatten_args(val, include_unknown_args)
             elif isinstance(val, (str, bool, int, float)) or include_unknown_args:
                 flattend_kwargs[key] = val
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -158,16 +158,20 @@ def build_target(self, node, args, kwargs, targetclass):
         args = self.flatten_args(args)
         if not args or not isinstance(args[0], str):
             return
-        kwargs = self.flatten_kwargs(kwargs, True)
         name = args[0]
         srcqueue = [node]
+
+        # Process the soruces BEFORE flattening the kwargs, to preserve the original nodes
         if 'sources' in kwargs:
-            srcqueue += kwargs['sources']
+            srcqueue += mesonlib.listify(kwargs['sources'])
+
+        kwargs = self.flatten_kwargs(kwargs, True)
 
         source_nodes = []
         while srcqueue:
             curr = srcqueue.pop(0)
             arg_node = None
+            assert(isinstance(curr, BaseNode))
             if isinstance(curr, FunctionNode):
                 arg_node = curr.args
             elif isinstance(curr, ArrayNode):


Test patch:
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
--- a/test cases/unit/55 introspection/meson.build	
+++ b/test cases/unit/55 introspection/meson.build	
@@ -25,7 +25,7 @@ var2 = 2.to_string()
 var3 = 'test3'
 
 t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: true, build_by_default: get_option('test_opt2'))
-t2 = executable('test@0@'.format('@0@'.format(var2)), 't2.cpp', link_with: [staticlib])
+t2 = executable('test@0@'.format('@0@'.format(var2)), sources: ['t2.cpp'], link_with: [staticlib])
 t3 = executable(var3, 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1])
 
 ### BEGIN: Test inspired by taisei: https://github.com/taisei-project/taisei/blob/master/meson.build#L293