userdiff: support Java type parameters

A class or interface in Java can have type parameters following the name
in the declared type, surrounded by angle brackets (paired less than and
greater than signs).[2]   The type parameters -- `A` and `B` in the
examples -- may follow the class name immediately:

    public class ParameterizedClass<A, B> {
    }

or may be separated by whitespace:

    public class SpaceBeforeTypeParameters <A, B> {
    }

A part of the builtin userdiff pattern for Java matches declarations of
classes, enums, and interfaces.  The regular expression requires at
least one whitespace character after the name of the declared type.
This disallows matching for opening angle bracket of type parameters
immediately after the name of the type.  Mandatory whitespace after the
name of the type also disallows using the pattern in repositories with a
fairly common code style that puts braces for the body of a class on
separate lines:

    class WithLineBreakBeforeOpeningBrace
    {
    }

Support matching Java code in more diverse code styles and declarations
of classes and interfaces with type parameters immediately following the
name of the type in the builtin userdiff pattern for Java.  Do so by
just matching anything until the end of the line after the keywords for
the kind of type being declared.

[1] Since Java 5 released in 2004.
[2] Detailed description is available in the Java Language
    Specification, sections "Type Variables" and "Parameterized Types":
    https://docs.oracle.com/javase/specs/jls/se17/html/jls-4.html#jls-4.4

Signed-off-by: Andrei Rybak <rybak.a.v@gmail.com>
Reviewed-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Andrei Rybak 2023-02-08 00:42:57 +01:00 коммит произвёл Junio C Hamano
Родитель a6a323b31e
Коммит 39226a8dac
7 изменённых файлов: 37 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,6 @@
class RIGHT
{
static int ONE;
static int TWO;
static int ChangeMe;
}

Просмотреть файл

@ -0,0 +1,6 @@
class RIGHT <TYPE, PARAMS, AFTER, SPACE> {
static int ONE;
static int TWO;
static int THREE;
private A ChangeMe;
}

Просмотреть файл

@ -0,0 +1,6 @@
class RIGHT<A, B> {
static int ONE;
static int TWO;
static int THREE;
private A ChangeMe;
}

Просмотреть файл

@ -0,0 +1,6 @@
class RIGHT<A, B> implements List<A> {
static int ONE;
static int TWO;
static int THREE;
private A ChangeMe;
}

Просмотреть файл

@ -0,0 +1,6 @@
interface RIGHT<A, B> {
static int ONE;
static int TWO;
static int THREE;
public B foo(A ChangeMe);
}

Просмотреть файл

@ -0,0 +1,6 @@
interface RIGHT<A, B> extends Function<A, B> {
static int ONE;
static int TWO;
static int THREE;
public B foo(A ChangeMe);
}

Просмотреть файл

@ -171,7 +171,7 @@ PATTERNS("html",
PATTERNS("java",
"!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
/* Class, enum, and interface declarations */
"^[ \t]*(([a-z]+[ \t]+)*(class|enum|interface)[ \t]+[A-Za-z][A-Za-z0-9_$]*[ \t]+.*)$\n"
"^[ \t]*(([a-z]+[ \t]+)*(class|enum|interface)[ \t]+.*)$\n"
/* Method definitions; note that constructor signatures are not */
/* matched because they are indistinguishable from method calls. */
"^[ \t]*(([A-Za-z_<>&][][?&<>.,A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$",