xgettext: Rust: Recognize 'gettextrs::gettext' invocations like 'gettext'

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.
This commit is contained in:
Bruno Haible 2025-10-12 16:31:10 +02:00
parent 731022e254
commit 4d64f8c471
4 changed files with 36 additions and 7 deletions

3
NEWS
View File

@ -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

View 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);

View File

@ -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}

View File

@ -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}