{"thread":{"id":"56263","subject":"[PATCH v6] userdiff: improve java hunk header regex","startedAt":"2021-08-11T17:51:21Z","lastAt":"2021-08-11T17:51:21Z","messageCount":1,"participants":["Tassilo Horn"],"isPatch":true,"patchVersion":6,"patchTotal":null},"messages":[{"id":"432499","messageId":"20210811175104.48119-1-tsdh@gnu.org","threadId":"56263","inReplyTo":null,"subject":"[PATCH v6] userdiff: improve java hunk header regex","fromName":"Tassilo Horn","fromEmail":"tsdh@gnu.org","sentAt":"2021-08-11T17:51:04Z","receivedAt":"2021-08-11T17:51:21Z","isPatch":true,"sender":{"key":"tsdh@gnu.org","avatar":"https://avatars.githubusercontent.com/u/103854?v=4"},"body":"Currently, the git diff hunk headers show the wrong method signature if the\nmethod has a qualified return type, an array return type, or a generic return\ntype because the regex doesn't allow dots (.), [], or < and > in the return\ntype.  Also, type parameter declarations couldn't be matched.\n\nAdd several t4018 tests asserting the right hunk headers for different cases:\n\n  - enum constant change\n  - change in generic method with bounded type parameters\n  - change in generic method with wildcard\n  - field change in a nested class\n\nSigned-off-by: Tassilo Horn <tsdh@gnu.org>\n---\n t/t4018/java-class-member-function          | 4 ++++\n t/t4018/java-enum-constant                  | 6 ++++++\n t/t4018/java-method-return-generic-bounded  | 9 +++++++++\n t/t4018/java-method-return-generic-wildcard | 9 +++++++++\n t/t4018/java-nested-field                   | 6 ++++++\n userdiff.c                                  | 6 +++++-\n 6 files changed, 39 insertions(+), 1 deletion(-)\n create mode 100644 t/t4018/java-enum-constant\n create mode 100644 t/t4018/java-method-return-generic-bounded\n create mode 100644 t/t4018/java-method-return-generic-wildcard\n create mode 100644 t/t4018/java-nested-field\n\ndiff --git a/t/t4018/java-class-member-function b/t/t4018/java-class-member-function\nindex 298bc7a71b..3b95f68b3b 100644\n--- a/t/t4018/java-class-member-function\n+++ b/t/t4018/java-class-member-function\n@@ -3,6 +3,10 @@ public class Beer\n \tint special;\n \tpublic static void main(String RIGHT[])\n \t{\n+\t\tsomeMethodCall();\n+\t\tsomeOtherMethod(\"17\")\n+\t\t\t.doThat();\n+\t\t// Whatever\n \t\tSystem.out.print(\"ChangeMe\");\n \t}\n }\ndiff --git a/t/t4018/java-enum-constant b/t/t4018/java-enum-constant\nnew file mode 100644\nindex 0000000000..a1931c8379\n--- /dev/null\n+++ b/t/t4018/java-enum-constant\n@@ -0,0 +1,6 @@\n+private enum RIGHT {\n+    ONE,\n+    TWO,\n+    THREE,\n+    ChangeMe\n+}\ndiff --git a/t/t4018/java-method-return-generic-bounded b/t/t4018/java-method-return-generic-bounded\nnew file mode 100644\nindex 0000000000..66dd78c379\n--- /dev/null\n+++ b/t/t4018/java-method-return-generic-bounded\n@@ -0,0 +1,9 @@\n+class MyExample {\n+    public <T extends Bar & Foo<T>, R> Map<T, R[]> foo(String[] RIGHT) {\n+        someMethodCall();\n+        someOtherMethod()\n+            .doThat();\n+        // Whatever...\n+        return (List<T>) Arrays.asList(\"ChangeMe\");\n+    }\n+}\ndiff --git a/t/t4018/java-method-return-generic-wildcard b/t/t4018/java-method-return-generic-wildcard\nnew file mode 100644\nindex 0000000000..96e9e5f2c1\n--- /dev/null\n+++ b/t/t4018/java-method-return-generic-wildcard\n@@ -0,0 +1,9 @@\n+class MyExample {\n+    public List<? extends Comparable> foo(String[] RIGHT) {\n+        someMethodCall();\n+        someOtherMethod()\n+            .doThat();\n+        // Whatever...\n+        return Arrays.asList(\"ChangeMe\");\n+    }\n+}\ndiff --git a/t/t4018/java-nested-field b/t/t4018/java-nested-field\nnew file mode 100644\nindex 0000000000..d92d3ec688\n--- /dev/null\n+++ b/t/t4018/java-nested-field\n@@ -0,0 +1,6 @@\n+class MyExample {\n+    private static class RIGHT {\n+        // change an inner class field\n+        String inner = \"ChangeMe\";\n+    }\n+}\ndiff --git a/userdiff.c b/userdiff.c\nindex 3c3bbe38b0..3452aacd6d 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -142,7 +142,11 @@ PATTERNS(\"html\",\n \t \"[^<>= \\t]+\"),\n PATTERNS(\"java\",\n \t \"!^[ \\t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\\n\"\n-\t \"^[ \\t]*(([A-Za-z_][A-Za-z_0-9]*[ \\t]+)+[A-Za-z_][A-Za-z_0-9]*[ \\t]*\\\\([^;]*)$\",\n+\t /* Class, enum, and interface declarations */\n+\t \"^[ \\t]*(([a-z]+[ \\t]+)*(class|enum|interface)[ \\t]+[A-Za-z][A-Za-z0-9_$]*[ \\t]+.*)$\\n\"\n+\t /* Method definitions; note that constructor signatures are not */\n+\t /* matched because they are indistinguishable from method calls. */\n+\t \"^[ \\t]*(([A-Za-z_<>&][][?&<>.,A-Za-z_0-9]*[ \\t]+)+[A-Za-z_][A-Za-z_0-9]*[ \\t]*\\\\([^;]*)$\",\n \t /* -- */\n \t \"[a-zA-Z_][a-zA-Z0-9_]*\"\n \t \"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?\"\n-- \n2.32.0\n\n"}]}