[gnome-builder] meson: fixed language parsing in meson files



commit c2e10cdecc2c62f6a0f012fe44e0a15b2f579376
Author: Günther Wagner <info gunibert de>
Date:   Tue Oct 12 21:00:32 2021 +0200

    meson: fixed language parsing in meson files
    
    Sticking closer to the reference of possible declarations.

 src/plugins/meson-templates/resources/meson.build |  2 +-
 src/plugins/meson/gbp-meson-build-system.c        | 83 ++++++++++++++---------
 src/plugins/meson/meson.build                     | 13 ++++
 src/plugins/meson/test-meson-build-system.c       | 46 +++++++++++++
 4 files changed, 110 insertions(+), 34 deletions(-)
---
diff --git a/src/plugins/meson-templates/resources/meson.build 
b/src/plugins/meson-templates/resources/meson.build
index d3177e7fa..793991c48 100644
--- a/src/plugins/meson-templates/resources/meson.build
+++ b/src/plugins/meson-templates/resources/meson.build
@@ -1,4 +1,4 @@
-project('{{name}}',{{if language == "c"}} 'c',{{else if language == "c++"}} ['cpp', 'c'],{{else if language 
== "vala"}} ['c', 'vala'],{{else if language == "c♯"}} 'cs',{{end}}
+project('{{name}}',{{if language == "c"}} 'c',{{else if language == "c++"}} ['cpp', 'c'],{{else if language 
== "vala"}} ['c', 'vala'],{{else if language == "c♯"}} 'cs',{{else if language == "rust"}} 'rust', {{end}}
 
           version: '{{project_version}}',
     meson_version: '>= 0.50.0',
diff --git a/src/plugins/meson/gbp-meson-build-system.c b/src/plugins/meson/gbp-meson-build-system.c
index d9de95904..ddf787a3c 100644
--- a/src/plugins/meson/gbp-meson-build-system.c
+++ b/src/plugins/meson/gbp-meson-build-system.c
@@ -756,50 +756,67 @@ build_system_iface_init (IdeBuildSystemInterface *iface)
   iface->supports_language = gbp_meson_build_system_supports_language;
 }
 
-/**
- * This could be 'projectname', ['c', 'rust'], ... or 'projectname', 'rust', ...
- */
+
 static char **
-parse_language (gchar *language_string)
+split_language (gchar *raw_language_string)
 {
-  if (strstr(language_string, "["))
+  g_autofree gchar *copy = NULL;
+  GString *str = g_string_new (raw_language_string);
+  g_string_replace (str, "'", "", -1);
+  g_string_replace (str, " ", "", -1);
+  g_string_replace (str, "\n", "", -1);
+  copy = g_string_free (str, FALSE);
+
+  return g_strsplit (copy, ",", -1);
+}
+
+/**
+ * This could be
+ * 1) without language
+ * 2) 'projectname', 'c' with only one language
+ * 3) 'projectname', 'c', 'c++' with variadic as languages
+ * 4) 'projectname', ['c', 'c++'] with an list as languages
+ */
+char **
+parse_languages (const gchar *raw_language_string)
+{
+  g_autofree gchar *language_string = NULL;
+  gchar *cur = (gchar *) raw_language_string;
+  gchar *cur2;
+  cur = g_strstr_len (cur, -1, ",");
+  if (cur == NULL) goto failure;
+  cur++;
+  cur2 = cur;
+  while (*cur2 != ':' || *cur2 == '\0')
+    {
+      if (*cur2 == '[')
+        {
+          cur2 = g_strstr_len (cur2, -1, "]");
+          if (cur2 == NULL) goto failure;
+          cur2++;
+          break;
+        }
+      cur2++;
+    }
+  if (*cur2 == ':') while(*cur2 != ',') cur2--;
+  if (cur2-cur <= 0) goto failure;
+  language_string = g_strndup (cur, cur2-cur);
+
+  if (strstr(language_string, "[") || strstr(language_string, "]"))
     {
       gchar *begin = NULL;
       gchar *end = NULL;
       g_autofree gchar *copy = NULL;
-      GString *gstring = NULL;
 
       if ((begin = strstr(language_string, "[")) == NULL) goto failure;
       if ((end = strstr(language_string, "]")) == NULL) goto failure;
       copy = g_strndup (begin + 1, end-begin - 1);
 
-      gstring = g_string_new (copy);
-      g_string_replace (gstring, "'", "", -1);
-      g_string_replace (gstring, " ", "", -1);
-      copy = g_string_free (gstring, FALSE);
-
-      return g_strsplit (copy, ",", -1);
-    }
-  else
-    {
-      gchar **list = NULL;
-      g_autofree gchar *language = NULL;
-      GString *gstring = NULL;
-      g_autoptr(GStrvBuilder) builder = NULL;
-
-      list = g_strsplit (language_string, ",", -1);
-      language = g_strstrip (list[1]);
-
-      gstring = g_string_new (language);
-      g_string_replace (gstring, "'", "", -1);
-      language = g_string_free (gstring, FALSE);
-      g_strfreev (list);
-
-      builder = g_strv_builder_new ();
-      g_strv_builder_add (builder, g_steal_pointer (&language));
-      return g_strv_builder_end (builder);
+      return split_language (copy);
     }
 
+  return split_language (language_string);
+
 failure:
   return NULL;
 }
@@ -852,8 +869,8 @@ extract_metadata (GbpMesonBuildSystem *self,
   g_regex_match (regex, contents, 0, &match_info);
   while (g_match_info_matches (match_info))
     {
-      gchar *str = g_match_info_fetch (match_info, 1);
-      self->languages = parse_language (str);
+      const gchar *str = g_match_info_fetch (match_info, 1);
+      self->languages = parse_languages (str);
 
       g_match_info_next (match_info, NULL);
     }
diff --git a/src/plugins/meson/meson.build b/src/plugins/meson/meson.build
index 4e16a7da5..eb30d3a1a 100644
--- a/src/plugins/meson/meson.build
+++ b/src/plugins/meson/meson.build
@@ -27,4 +27,17 @@ plugin_meson_resources = gnome.compile_resources(
 
 plugins_sources += plugin_meson_resources
 
+test_sources += files([
+  'test-meson-build-system.c',
+  'gbp-meson-build-system.c',
+  'gbp-meson-toolchain.c',
+  'gbp-meson-utils.c',
+])
+
+test_meson = executable('test-meson', test_sources,
+        c_args: test_cflags,
+  dependencies: [ libide_foundry_dep ],
+)
+test('test-meson', test_meson, env: test_env)
+
 endif
diff --git a/src/plugins/meson/test-meson-build-system.c b/src/plugins/meson/test-meson-build-system.c
new file mode 100644
index 000000000..07117749d
--- /dev/null
+++ b/src/plugins/meson/test-meson-build-system.c
@@ -0,0 +1,46 @@
+#include <glib.h>
+
+const gchar **parse_languages (gchar *language_string);
+
+static void
+meson_test_parse_languages (void)
+{
+  struct {
+    gchar *input;
+    gchar **expected;
+  } cases[] = {
+      { .input = "'testproject', 'rust'", .expected = (gchar*[]){ "rust", NULL } },
+      { .input = "'testproject', 'rust', 'c'", .expected = (gchar*[]){ "rust", "c", NULL } },
+      { .input = "'testproject', 'rust', version: '3.0'", .expected = (gchar*[]){ "rust", NULL } },
+      { .input = "testproject, rust, version: 3.0, default_options: ['warning_level=2']", .expected = 
(gchar*[]){ "rust", NULL } },
+      { .input = "testproject\n\n,\n rust, \nversion: 3.0, default_options: ['warning_level=2']", .expected 
= (gchar*[]){ "rust", NULL } },
+      { .input = "testproject\n\n,\n ['rust'], \nversion: 3.0, default_options: ['warning_level=2']", 
.expected = (gchar*[]){ "rust", NULL } },
+      { .input = "testproject\n\n,\n ['rust']", .expected = (gchar*[]){ "rust", NULL } },
+      { .input = "testproject\n\n,\n ['c', 'c++'], \nversion: 3.0, default_options: ['warning_level=2']", 
.expected = (gchar*[]){ "c", "c++", NULL } },
+      { .input = "testproject\n\n,\n ['c', 'c++', \nversion: 3.0", .expected = NULL},
+      { .input = "testproject\n\n,\n 'c', 'c++', \nversion: 3.0", .expected = (gchar*[]){ "c", "c++", NULL } 
},
+      { .input = "testproject\n\n,\n 'c', 'c++'], \nversion: 3.0", .expected = NULL },
+      { .input = "'testproject',\nversion: 3.0", .expected = NULL },
+      { .input = "'projectname'", .expected = NULL },
+  };
+
+  const guint n_cases = G_N_ELEMENTS (cases);
+
+  for (guint i = 0; i < n_cases; i++)
+    {
+      const gchar **languages = parse_languages (cases[i].input);
+
+      g_assert_cmpstrv (cases[i].expected, languages);
+    }
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func("/meson/parse_languages", meson_test_parse_languages);
+
+  return g_test_run ();
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]