]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xgettext: Rust: Recognize 'gettextrs::gettext' invocations like 'gettext'
authorBruno Haible <bruno@clisp.org>
Sun, 12 Oct 2025 14:31:10 +0000 (16:31 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 12 Oct 2025 14:32:24 +0000 (16:32 +0200)
invocations.

Reported by Schmiddiii <gnu-savannah@schmidhuberj.de>
at <https://savannah.gnu.org/bugs/?67601>.

* gettext-tools/src/x-rust.c (ts_symbol_scoped_identifier): New variable.
(extract_from_function_call): Accept a scoped_identifier as first argument.
(extract_from_node): Allow a scoped_identifier as callee.
(extract_rust): Initialize ts_symbol_scoped_identifier.
* gettext-tools/tests/xgettext-rust-1: Add another test case.
* gettext-tools/tests/xgettext-rust-6: Likewise.
* NEWS: Mention the fix.

NEWS
gettext-tools/src/x-rust.c
gettext-tools/tests/xgettext-rust-1
gettext-tools/tests/xgettext-rust-6

diff --git a/NEWS b/NEWS
index 730c97f8c5cf012b284d051eb48a14fba8ca7146..bb7c4dc778bd851f4c9ee71bda5847e94158dfb7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ Version 0.27 - October 2025
     - 'msgfmt -c' now verifies the syntax of translations of OCaml format
       strings.
     - A new example 'hello-ocaml' has been added.
+  * Rust:
+    - xgettext now recognizes 'gettextrs::gettext' invocations, like 'gettext'
+      invocations.
 
 # libgettextpo library:
   * The function 'po_message_get_format' now supports distinguishing whether
index 8561e4c1797bd1e81dc4385e710a9419783df085..be769cefac1b755518a736ddb77e17a574ac9532 100644 (file)
@@ -212,6 +212,7 @@ static TSSymbol ts_symbol_raw_string_literal;
 static TSSymbol ts_symbol_string_content;
 static TSSymbol ts_symbol_escape_sequence;
 static TSSymbol ts_symbol_identifier;
+static TSSymbol ts_symbol_scoped_identifier;
 static TSSymbol ts_symbol_call_expression;
 static TSSymbol ts_symbol_macro_invocation;
 static TSSymbol ts_symbol_arguments;
@@ -515,7 +516,8 @@ static void extract_from_node (TSNode node,
                                message_list_ty *mlp);
 
 /* Extracts messages from the function call consisting of
-     - CALLEE_NODE: a tree node of type 'identifier',
+     - CALLEE_NODE: a tree node of type 'identifier' or
+       a tree node of type 'scoped_identifier' with at least 1 named child,
      - ARGS_NODE: a tree node of type 'arguments'.
    Extracted messages are added to MLP.  */
 static void
@@ -526,9 +528,17 @@ extract_from_function_call (TSNode callee_node,
 {
   uint32_t args_count = ts_node_child_count (args_node);
 
+  TSNode callee_last_identifier_node;
+  if (ts_node_symbol (callee_node) == ts_symbol_identifier)
+    callee_last_identifier_node = callee_node;
+  else
+    /* Here ts_node_named_child_count (callee_node) >= 1.  */
+    callee_last_identifier_node =
+      ts_node_named_child (callee_node, ts_node_named_child_count (callee_node) - 1);
+
   string_desc_t callee_name =
-    sd_new_addr (ts_node_end_byte (callee_node) - ts_node_start_byte (callee_node),
-                 contents + ts_node_start_byte (callee_node));
+    sd_new_addr (ts_node_end_byte (callee_last_identifier_node) - ts_node_start_byte (callee_last_identifier_node),
+                 contents + ts_node_start_byte (callee_last_identifier_node));
 
   /* Context iterator.  */
   flag_context_list_iterator_ty next_context_iter =
@@ -960,7 +970,9 @@ extract_from_node (TSNode node,
       if (! ts_node_eq (ts_node_child_by_field_id (node, ts_field_function),
                         callee_node))
         abort ();
-      if (ts_node_symbol (callee_node) == ts_symbol_identifier)
+      if (ts_node_symbol (callee_node) == ts_symbol_identifier
+          || (ts_node_symbol (callee_node) == ts_symbol_scoped_identifier
+              && ts_node_named_child_count (callee_node) >= 1))
         {
           TSNode args_node = ts_node_child_by_field_id (node, ts_field_arguments);
           /* This is the field called 'arguments'.  */
@@ -1119,6 +1131,7 @@ extract_rust (FILE *f,
       ts_symbol_string_content     = ts_language_symbol ("string_content", true);
       ts_symbol_escape_sequence    = ts_language_symbol ("escape_sequence", true);
       ts_symbol_identifier         = ts_language_symbol ("identifier", true);
+      ts_symbol_scoped_identifier  = ts_language_symbol ("scoped_identifier", true);
       ts_symbol_call_expression    = ts_language_symbol ("call_expression", true);
       ts_symbol_macro_invocation   = ts_language_symbol ("macro_invocation", true);
       ts_symbol_arguments          = ts_language_symbol ("arguments", true);
index 234019abc1c1542cfb88c4b7b9d29b7c31b28c29..1cb79aa3805a53a577cdb551ab39ee1765ef21a8 100755 (executable)
@@ -4,7 +4,7 @@
 # Test Rust support: Simple things.
 
 cat <<\EOF > xg-rs-1.rs
-use gettext_rs::gettext;
+use gettextrs::gettext;
 
 pub trait TestCase {
   fn TestCase() {
@@ -26,6 +26,8 @@ pub trait TestCase {
     String test5 = gettext(r#"first line
 second line
 third line"#);
+    // scoped identifier
+    String test6 = gettextrs::gettext("Test String 6");
   }
 }
 EOF
@@ -61,6 +63,10 @@ msgid ""
 "second line\n"
 "third line"
 msgstr ""
+
+#. scoped identifier
+msgid "Test String 6"
+msgstr ""
 EOF
 
 : ${DIFF=diff}
index 307822cd06a6ad5f00f60f5ece294afae6d644d0..15b4516e7dce18ad6f9660bd6fdb874d54f15522 100755 (executable)
@@ -9,8 +9,9 @@ fn main ()
   tr! ("Hello {}");
   tr! (gettext /*x*/ ("Hello1"));
   tr! [foo(), gettext ("Hello2")];
-  tr ! (tr ! ("Hello3"));
-  tr! (foo(), tr! ("Hello4"));
+  tr! (gettextrs::gettext ("Hello3"));
+  tr ! (tr ! ("Hello4"));
+  tr! (foo(), tr! ("Hello5"));
 }
 EOF
 
@@ -24,6 +25,9 @@ msgstr ""
 
 msgid "Hello2"
 msgstr ""
+
+msgid "Hello3"
+msgstr ""
 EOF
 
 : ${DIFF=diff}
@@ -49,6 +53,9 @@ msgstr ""
 
 msgid "Hello4"
 msgstr ""
+
+msgid "Hello5"
+msgstr ""
 EOF
 
 : ${DIFF=diff}