]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xgettext: Fix parsing of JavaScript template literals inside functions.
authorBruno Haible <bruno@clisp.org>
Sun, 28 Jul 2019 17:21:32 +0000 (19:21 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 13 Apr 2020 10:54:22 +0000 (12:54 +0200)
Reported by Dmitry Vinnik <vinnik.dmitry07@gmail.com>
in <https://savannah.gnu.org/bugs/?56678>.

* gettext-tools/src/x-javascript.c (brace_depths, brace_depths_alloc): New
variables.
(brace_depth): Remove variable.
(new_brace_depth_level): New function.
(phase5_get): Invoke it. Access the top of the brace_depths stack.
(extract_javascript): Don't set brace_depth. Invoke new_brace_depth_level
instead.
* gettext-tools/tests/xgettext-javascript-7: Test template literals inside a
function.

gettext-tools/src/x-javascript.c
gettext-tools/tests/xgettext-javascript-7

index dd19b372e46c4e601bb9e4681cc9d0f32e598176..7ac5b24725f479e6d33d18e7cc2db5a189ebe844 100644 (file)
@@ -929,12 +929,30 @@ phase5_scan_regexp (void)
       phase2_ungetc (c);
 }
 
-/* Number of open '{' tokens.  */
-static int brace_depth;
-
 /* Number of open template literals `...${  */
 static int template_literal_depth;
 
+/* Number of open '{' tokens, at each template literal level.
+   The "current" element is brace_depths[template_literal_depth].  */
+static int *brace_depths;
+/* Number of allocated elements in brace_depths.  */
+static size_t brace_depths_alloc;
+
+/* Adds a new brace_depths level after template_literal_depth was
+   incremented.  */
+static void
+new_brace_depth_level (void)
+{
+  if (template_literal_depth == brace_depths_alloc)
+    {
+      brace_depths_alloc = 2 * brace_depths_alloc + 1;
+      /* Now template_literal_depth < brace_depths_alloc.  */
+      brace_depths =
+        (int *) xrealloc (brace_depths, brace_depths_alloc * sizeof (int));
+    }
+  brace_depths[template_literal_depth] = 0;
+}
+
 /* Number of open XML elements.  */
 static int xml_element_depth;
 static bool inside_embedded_js_in_xml;
@@ -1227,6 +1245,7 @@ phase5_get (token_ty *tp)
                     mixed_string_buffer_destroy (&msb);
                     tp->type = last_token_type = token_type_ltemplate;
                     template_literal_depth++;
+                    new_brace_depth_level ();
                     break;
                   }
 
@@ -1357,15 +1376,15 @@ phase5_get (token_ty *tp)
           if (xml_element_depth > 0 && !inside_embedded_js_in_xml)
             inside_embedded_js_in_xml = true;
           else
-            brace_depth++;
+            brace_depths[template_literal_depth]++;
           tp->type = last_token_type = token_type_other;
           return;
 
         case '}':
           if (xml_element_depth > 0 && inside_embedded_js_in_xml)
             inside_embedded_js_in_xml = false;
-          else if (brace_depth > 0)
-            brace_depth--;
+          else if (brace_depths[template_literal_depth] > 0)
+            brace_depths[template_literal_depth]--;
           else if (template_literal_depth > 0)
             {
               /* Middle or right part of template literal.  */
@@ -1695,8 +1714,8 @@ extract_javascript (FILE *f,
   last_comment_line = -1;
   last_non_comment_line = -1;
 
-  brace_depth = 0;
   template_literal_depth = 0;
+  new_brace_depth_level ();
   xml_element_depth = 0;
   inside_embedded_js_in_xml = false;
 
index c9516ec91c82008a151cfd045ca4083a1937d660..2d612a96ddce3b4e195168e275ddc5664958c409 100755 (executable)
@@ -17,6 +17,10 @@ var s7 = _(tag`A template literal with a tag`);
 var s8 = `a${`b${`c`+d}`}e`;
 var s9 = _("a normal string");
 var s10 = `abc${foo({},_('should be extracted'))}xyz`;
+var f1 = function () {
+  return _("first normal string") + `${foo}` + _("second normal string");
+};
+var s11 = _("another normal string");
 EOF
 
 : ${XGETTEXT=xgettext}
@@ -65,6 +69,15 @@ msgstr ""
 
 msgid "should be extracted"
 msgstr ""
+
+msgid "first normal string"
+msgstr ""
+
+msgid "second normal string"
+msgstr ""
+
+msgid "another normal string"
+msgstr ""
 EOF
 
 : ${DIFF=diff}