From: Bruno Haible Date: Tue, 5 Dec 2023 15:07:38 +0000 (+0100) Subject: xgettext: Java: Flag strings on which the method 'formatted' is used as java-printf... X-Git-Tag: v0.23~282 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1381b84beaf968909a64e9785c4d63d82784670;p=thirdparty%2Fgettext.git xgettext: Java: Flag strings on which the method 'formatted' is used as java-printf-format. * gettext-tools/src/x-java.c (token_type_semicolon): New enum item. (phase5_get): Recognize semicolon tokens. (extract_parenthesized): Handle method invocation .formatted. Return when a semicolon was seen. * gettext-tools/tests/xgettext-java-8: New file, based on gettext-tools/tests/xgettext-vala-6. * gettext-tools/tests/xgettext-java-9: New file, based on gettext-tools/tests/xgettext-vala-7. * gettext-tools/tests/Makefile.am (TESTS): Add them. * NEWS: Mention the change. --- diff --git a/NEWS b/NEWS index a99ecc85f..2e96a6120 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ Version 0.23 - December 2023 * Programming languages support: - Python: xgettext now recognizes the f-string syntax. + - Java: Improved recognition of format strings when the String.formatted + method is used. - Vala: Improved recognition of format strings when the string.printf method is used. - Glade: xgettext has improved support for GtkBuilder 4. diff --git a/gettext-tools/src/x-java.c b/gettext-tools/src/x-java.c index 37a9f54dd..469c036c4 100644 --- a/gettext-tools/src/x-java.c +++ b/gettext-tools/src/x-java.c @@ -574,6 +574,7 @@ enum token_type_ty token_type_number, /* 1.23 */ token_type_symbol, /* identifier, keyword, null */ token_type_plus, /* + */ + token_type_semicolon, /* ; */ token_type_other /* character literal, misc. operator */ }; typedef enum token_type_ty token_type_ty; @@ -1312,6 +1313,11 @@ phase5_get (token_ty *tp) } return; + case ';': + /* Semicolon. */ + tp->type = token_type_semicolon; + return; + default: /* Misc. operator. */ tp->type = token_type_other; @@ -1586,6 +1592,34 @@ extract_parenthesized (message_list_ty *mlp, token_type_ty terminator, return true; } paren_nesting_depth--; + /* Test whether the next tokens are '.' and 'formatted'. */ + { + token_ty token2; + x_java_lex (&token2); + if (token2.type == token_type_dot) + { + token_ty token3; + x_java_lex (&token3); + if (token3.type == token_type_symbol + && strcmp (token3.string, "formatted") == 0) + { + /* Mark the messages found in the region as java-printf-format + a posteriori. */ + inner_region->for_formatstring[XFORMAT_SECONDARY].is_format = yes_according_to_context; + struct remembered_message_list_ty *rmlp = + inner_region->for_formatstring[XFORMAT_SECONDARY].remembered; + size_t i; + for (i = 0; i < rmlp->nitems; i++) + { + struct remembered_message_ty *rmp = &rmlp->item[i]; + set_format_flag_from_context (rmp->mp, rmp->plural, &rmp->pos, + XFORMAT_SECONDARY, inner_region); + } + } + x_java_unlex (&token3); + } + x_java_unlex (&token2); + } next_context_iter = null_context_list_iterator; state = 0; continue; @@ -1676,6 +1710,11 @@ extract_parenthesized (message_list_ty *mlp, token_type_ty terminator, state = 0; continue; + case token_type_semicolon: + arglist_parser_done (argparser, arg); + unref_region (inner_region); + return false; + case token_type_eof: arglist_parser_done (argparser, arg); unref_region (inner_region); diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 9e37ff142..d5dd1131a 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -110,7 +110,8 @@ TESTS = gettext-1 gettext-2 \ xgettext-gsettings-1 \ xgettext-its-1 xgettext-its-2 \ xgettext-java-1 xgettext-java-2 xgettext-java-3 xgettext-java-4 \ - xgettext-java-5 xgettext-java-6 xgettext-java-7 \ + xgettext-java-5 xgettext-java-6 xgettext-java-7 xgettext-java-8 \ + xgettext-java-9 \ xgettext-java-stackovfl-1 xgettext-java-stackovfl-2 \ xgettext-java-stackovfl-3 xgettext-java-stackovfl-4 \ xgettext-javascript-1 xgettext-javascript-2 xgettext-javascript-3 \ diff --git a/gettext-tools/tests/xgettext-java-8 b/gettext-tools/tests/xgettext-java-8 new file mode 100644 index 000000000..15cd7bcb7 --- /dev/null +++ b/gettext-tools/tests/xgettext-java-8 @@ -0,0 +1,53 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test Java support: formatted and format strings. + +: ${XGETTEXT=xgettext} + +cat <<\EOF > xg-j-8.java +"%s".formatted(_("Hello 1")); +_("Explanation: %s").formatted(_("Hello 2")); +_("No error 1"); +_("No error 2").formatted(); +(_("No error 3")).formatted(); +foo(_("No error 4")).formatted(); +EOF + +${XGETTEXT} --omit-header --no-location \ + -k_ --flag=_:1:pass-java-format --flag=_:1:pass-java-printf-format \ + -o xg-j-8.tmp xg-j-8.java \ + || Exit 1 +func_filter_POT_Creation_Date xg-j-8.tmp xg-j-8.po + +cat <<\EOF > xg-j-8.ok +msgid "Hello 1" +msgstr "" + +#, java-printf-format +msgid "Explanation: %s" +msgstr "" + +msgid "Hello 2" +msgstr "" + +msgid "No error 1" +msgstr "" + +#, java-printf-format +msgid "No error 2" +msgstr "" + +#, java-printf-format +msgid "No error 3" +msgstr "" + +msgid "No error 4" +msgstr "" +EOF + +: ${DIFF=diff} +${DIFF} xg-j-8.ok xg-j-8.po +result=$? + +exit $result diff --git a/gettext-tools/tests/xgettext-java-9 b/gettext-tools/tests/xgettext-java-9 new file mode 100644 index 000000000..81cc1f48e --- /dev/null +++ b/gettext-tools/tests/xgettext-java-9 @@ -0,0 +1,30 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test Java support: diagnostics for invalid format strings. + +: ${XGETTEXT=xgettext} + +cat <<\EOF > xg-j-9.java +_("Invalid Java format %z").formatted(); +EOF + +LANGUAGE= LC_ALL=C \ +${XGETTEXT} --omit-header --no-location \ + -k_ --flag=_:1:pass-java-format --flag=_:1:pass-java-printf-format \ + -o xg-j-9.tmp xg-j-9.java 2>xg-j-9.err \ + || Exit 1 +cat xg-j-9.err +grep 'warning: Although being used in a format string position, the msgid is not a valid Java printf format string.' xg-j-9.err >/dev/null || Exit 1 +func_filter_POT_Creation_Date xg-j-9.tmp xg-j-9.po + +cat <<\EOF > xg-j-9.ok +msgid "Invalid Java format %z" +msgstr "" +EOF + +: ${DIFF=diff} +${DIFF} xg-j-9.ok xg-j-9.po +result=$? + +exit $result