From: Bruno Haible Date: Sun, 12 Oct 2025 14:31:10 +0000 (+0200) Subject: xgettext: Rust: Recognize 'gettextrs::gettext' invocations like 'gettext' X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4d64f8c47129a7cc442a9e33b2e50ee029445608;p=thirdparty%2Fgettext.git xgettext: Rust: Recognize 'gettextrs::gettext' invocations like 'gettext' invocations. Reported by Schmiddiii at . * 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. --- diff --git a/NEWS b/NEWS index 730c97f8c..bb7c4dc77 100644 --- 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 diff --git a/gettext-tools/src/x-rust.c b/gettext-tools/src/x-rust.c index 8561e4c17..be769cefa 100644 --- a/gettext-tools/src/x-rust.c +++ b/gettext-tools/src/x-rust.c @@ -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); diff --git a/gettext-tools/tests/xgettext-rust-1 b/gettext-tools/tests/xgettext-rust-1 index 234019abc..1cb79aa38 100755 --- a/gettext-tools/tests/xgettext-rust-1 +++ b/gettext-tools/tests/xgettext-rust-1 @@ -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} diff --git a/gettext-tools/tests/xgettext-rust-6 b/gettext-tools/tests/xgettext-rust-6 index 307822cd0..15b4516e7 100755 --- a/gettext-tools/tests/xgettext-rust-6 +++ b/gettext-tools/tests/xgettext-rust-6 @@ -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}