runtime(java): Optionally highlight parameterised types

Commit: 
https://github.com/vim/vim/commit/beb02ed674bc61f179c4ff71e93bdeeb44fe9c4e
Author: Aliaksei Budavei <0x000...@gmail.com>
Date:   Thu Jun 20 21:00:53 2024 +0200

    runtime(java): Optionally highlight parameterised types
    
    In the presence of parameterised types whose names begin
    with a capital letter and end with a less-than sign "<" that
    introduces a type argument or a list of comma-separated type
    arguments, followed by a greater-than sign ">", a variable
    "g:java_highlight_generics" can be defined to have some
    components of such types uniformly coloured (by picking
    highlight groups for javaGenericsC{1,2}, javaWildcardBound).
    
    For example,
    ------------------------------------------------------------
    java.io.InputStream stream = java.io.InputStream.nullInputStream();
    java.util.function.Function<String,
        java.util.function.BiFunction<String, String, String>> updater =
            property -> (oldValue, newValue) -> oldValue;
    java.util.logging.LogManager.getLogManager()
        .updateConfiguration(stream, updater);
    ------------------------------------------------------------
    
    Note that the diamond form and explicit type arguments do
    not qualify for this kind of recognition.
    
    For example,
    ------------------------------------------------------------
    new java.util.HashSet<>().<String>toArray(new String[0]);
    ------------------------------------------------------------
    
    References:
    https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html#jls-4.5
    https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.9
    https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.12.2.1
    
    closes: #15050
    
    Signed-off-by: Aliaksei Budavei <0x000...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index c07c3a4ea..1460edd44 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1,4 +1,4 @@
-*syntax.txt*   For Vim version 9.1.  Last change: 2024 Jun 17
+*syntax.txt*   For Vim version 9.1.  Last change: 2024 Jun 19
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -2014,7 +2014,7 @@ Check the javaid.vim file for a list of all the packages 
that are supported.
 
 Function names are not highlighted, as the way to find functions depends on
 how you write Java code.  The syntax file knows two possible ways to highlight
-functions:
+headers of function declarations:
 
 If you write function declarations that are consistently indented by either
 a tab, or a space . . . or eight space character(s), you may want to set >
@@ -2032,10 +2032,14 @@ However, if you follow the Java guidelines about how 
functions and classes are
 supposed to be named (with respect to upper- and lowercase) and there is any
 amount of indentation, you may want to set >
        :let java_highlight_functions="style"
-If neither setting does work for you, but you would still want function
-declarations to be highlighted, create your own definitions by changing the
-definitions in java.vim or by creating your own java.vim that includes the
-original one and then adds the code to highlight functions.
+If neither setting does work for you, but you would still want headers of
+function declarations to be highlighted, modify the current syntax definitions
+or compose new ones.
+
+Higher-order function types can be hard to parse by eye, so uniformly toning
+down some of their components may be of value.  Provided that such type names
+conform to the Java naming guidelines, you may arrange it with >
+       :let java_highlight_generics=1
 
 In Java 1.1 the functions System.out.println() and System.err.println() should
 only be used for debugging.  Therefore it is possible to highlight debugging
diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim
index c2cba1a5f..b612ccaaa 100644
--- a/runtime/syntax/java.vim
+++ b/runtime/syntax/java.vim
@@ -146,6 +146,30 @@ if s:module_info_cur_buf
   syn keyword javaModuleExternal       to with
 endif
 
+" Fancy parameterised types (JLS-17, §4.5).
+"
+" Note that false positives may elsewhere occur whenever an identifier
+" is butted against a less-than operator.  Cf. (X<Y) and (X < Y).
+if exists("java_highlight_generics")
+  syn keyword javaWildcardBound contained extends super
+
+  " Parameterised types are delegated to javaGenerics (s:ctx.gsg) and
+  " are not matched with javaTypeArgument.
+  exec 'syn match javaTypeArgument contained "' . s:ff.Engine('\%#=2', '') . 
'?\|\%(\<\%(b\%(oolean\|yte\)\|char\|short\|int\|long\|float\|double\)\[\]\|\%(\<\K\k*\>\.\)*\<'
 . s:ff.UpperCase('[$_[:upper:]]', '[^a-z0-9]') . '\k*\>\)\%(\[\]\)*"'
+
+  for s:ctx in [{'dsg': 'javaDimExpr', 'gsg': 'javaGenerics', 'ghg': 
'javaGenericsC1', 'csg': 'javaGenericsX', 'c': ''},
+      \ {'dsg': 'javaDimExprX', 'gsg': 'javaGenericsX', 'ghg': 
'javaGenericsC2', 'csg': 'javaGenerics', 'c': ' contained'}]
+    " Consider array creation expressions of reifiable types.
+    exec 'syn region ' . s:ctx.dsg . ' contained transparent matchgroup=' . 
s:ctx.ghg . ' start="\[" end="\]" nextgroup=' . s:ctx.dsg . ' skipwhite skipnl'
+    exec 'syn region ' . s:ctx.gsg . s:ctx.c . ' transparent matchgroup=' . 
s:ctx.ghg . ' start=/' . s:ff.Engine('\%#=2', '') . '\%(\<\K\k*\>\.\)*\<' . 
s:ff.UpperCase('[$_[:upper:]]', '[^a-z0-9]') . '\k*\><\%([[:space:]
]*\%([?@]\|\<\%(b\%(oolean\|yte\)\|char\|short\|int\|long\|float\|double\)\[\]\|\%(\<\K\k*\>\.\)*\<'
 . s:ff.UpperCase('[$_[:upper:]]', '[^a-z0-9]') . '\k*\>\)\)\@=/ end=/>/ 
contains=' . s:ctx.csg . 
',javaAnnotation,javaTypeArgument,javaWildcardBound,javaType,@javaClasses 
nextgroup=' . s:ctx.dsg . ' skipwhite skipnl'
+  endfor
+
+  unlet s:ctx
+  hi def link javaWildcardBound Question
+  hi def link javaGenericsC1 javaFuncDef
+  hi def link javaGenericsC2 javaType
+endif
+
 if exists("java_highlight_java_lang_ids")
   let java_highlight_all=1
 endif
@@ -175,9 +199,15 @@ if exists("java_highlight_all")  || 
exists("java_highlight_java")  || exists("ja
   exec 'syn match javaC_JavaLang "\%(\<ModuleLayer\.\)\@' . s:ff.Peek('12', 
'') . '<=\<Controller\>"'
   exec 'syn match javaC_JavaLang "\%(\<Runtime\.\)\@' . s:ff.Peek('8', '') . 
'<=\<Version\>"'
   exec 'syn match javaC_JavaLang "\%(\<System\.\)\@' . s:ff.Peek('7', '') . 
'<=\<LoggerFinder\>"'
-  exec 'syn match javaC_JavaLang "\%(\<Enum\.\)\@' . s:ff.Peek('5', '') . 
'<=\<EnumDesc\>"'
-  syn keyword javaC_JavaLang Boolean Character Class ClassLoader Compiler 
Double Float Integer Long Math Number Object Process Runtime SecurityManager 
String StringBuffer Thread ThreadGroup Byte Short Void InheritableThreadLocal 
Package RuntimePermission ThreadLocal StrictMath StackTraceElement Enum 
ProcessBuilder StringBuilder ClassValue Module ModuleLayer StackWalker Record
+  syn keyword javaC_JavaLang Boolean Character ClassLoader Compiler Double 
Float Integer Long Math Number Object Process Runtime SecurityManager String 
StringBuffer Thread ThreadGroup Byte Short Void Package RuntimePermission 
StrictMath StackTraceElement ProcessBuilder StringBuilder Module ModuleLayer 
StackWalker Record
   syn match   javaC_JavaLang "\<System\>"      " See javaDebug.
+
+  if !exists("java_highlight_generics")
+    " The non-interface parameterised names of java.lang members.
+    exec 'syn match javaC_JavaLang "\%(\<Enum\.\)\@' . s:ff.Peek('5', '') . 
'<=\<EnumDesc\>"'
+    syn keyword javaC_JavaLang Class InheritableThreadLocal ThreadLocal Enum 
ClassValue
+  endif
+
   " As of JDK 21, java.lang.Compiler is no more (deprecated in JDK 9).
   syn keyword javaLangDeprecated Compiler
   syn cluster javaClasses add=javaC_JavaLang
@@ -217,7 +247,7 @@ if exists("java_space_errors")
 endif
 
 exec 'syn match javaUserLabel "^\s*\<\K\k*\>\%(\<default\>\)\@' . 
s:ff.Peek('7', '') . '<!\s*:"he=e-1'
-syn region  javaLabelRegion    transparent matchgroup=javaLabel 
start="\<case\>" matchgroup=NONE end=":\|->" 
contains=javaLabelCastType,javaLabelNumber,javaCharacter,javaString,javaConstant,@javaClasses,javaLabelDefault,javaLabelVarType,javaLabelWhenClause
+syn region  javaLabelRegion    transparent matchgroup=javaLabel 
start="\<case\>" matchgroup=NONE end=":\|->" 
contains=javaLabelCastType,javaLabelNumber,javaCharacter,javaString,javaConstant,@javaClasses,javaGenerics,javaLabelDefault,javaLabelVarType,javaLabelWhenClause
 syn region  javaLabelRegion    transparent matchgroup=javaLabel 
start="\<default\>\%(\s*\%(:\|->\)\)\@=" matchgroup=NONE end=":\|->" oneline
 " Consider grouped _default_ _case_ labels, i.e.
 " case null, default ->
@@ -332,7 +362,7 @@ syn match   javaSpecial "\u\x\x\x\x"
 
 " Method declarations (JLS-17, §8.4.3, §8.4.4, §9.4).
 if exists("java_highlight_functions")
-  syn cluster javaFuncParams 
contains=javaAnnotation,@javaClasses,javaType,javaVarArg,javaComment,javaLineComment
+  syn cluster javaFuncParams 
contains=javaAnnotation,@javaClasses,javaGenerics,javaType,javaVarArg,javaComment,javaLineComment
 
   if java_highlight_functions =~# '^indent[1-8]\=$'
     let s:last = java_highlight_functions[-1 :]
@@ -443,7 +473,7 @@ if exists("java_highlight_functions")
   " There is no recognition of expressions interspersed with comments
   " or of expressions whose parameterised parameter types are written
   " across multiple lines.
-  exec 'syn match javaLambdaDef "\k\@' . s:ff.Peek('4', '') . '<!([[:space:]
]*\%(\%(@\%(\K\k*\.\)*\K\k*\>\%((\_.\{-1,})\)\{-,1}[[:space:]
]\+\)*\%(final[[:space:]
]\+\)\=\%(\<\K\k*\>\.\)*\<\K\k*\>\%(<[^(){}]*[[:space:]-]\@' . s:ff.Peek('1', 
'') . '<!>\)\=\%(\%(\%(\[\]\)\+\|\.\.\.\)\)\=[[:space:]
]\+\<\K\k*\>\%(\[\]\)*\%(,[[:space:]
]*\)\=\)\+)[[:space:]
]*->" 
contains=javaAnnotation,javaParamModifier,javaLambdaVarType,javaType,@javaClasses,javaVarArg'
+  exec 'syn match javaLambdaDef "\k\@' . s:ff.Peek('4', '') . '<!([[:space:]
]*\%(\%(@\%(\K\k*\.\)*\K\k*\>\%((\_.\{-1,})\)\{-,1}[[:space:]
]\+\)*\%(final[[:space:]
]\+\)\=\%(\<\K\k*\>\.\)*\<\K\k*\>\%(<[^(){}]*[[:space:]-]\@' . s:ff.Peek('1', 
'') . '<!>\)\=\%(\%(\%(\[\]\)\+\|\.\.\.\)\)\=[[:space:]
]\+\<\K\k*\>\%(\[\]\)*\%(,[[:space:]
]*\)\=\)\+)[[:space:]
]*->" 
contains=javaAnnotation,javaParamModifier,javaLambdaVarType,javaType,@javaClasses,javaGenerics,javaVarArg'
   " Match: () ->
   "    | (a[, b, ...]) ->
   exec 'syn match javaLambdaDef "\k\@' . s:ff.Peek('4', '') . '<!([[:space:]
]*\%(\<\K\k*\>\%(,[[:space:]
]*\)\=\)*)[[:space:]
]*->"'
diff --git a/runtime/syntax/testdir/dumps/java_generics_00.dump 
b/runtime/syntax/testdir/dumps/java_generics_00.dump
new file mode 100644
index 000000000..0d7c4f917
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_00.dump
@@ -0,0 +1,20 @@
+>/+0#0000e05#ffffff0@1| |V|I|M|_|T|E|S|T|_|S|E|T|U|P| |l|e|t| 
|g|:|j|a|v|a|_|h|i|g|h|l|i|g|h|t|_|f|u|n|c|t|i|o|n|s| |=| |'|s|t|y|l|e|'| 
+0#0000000&@16
+|/+0#0000e05&@1| |V|I|M|_|T|E|S|T|_|S|E|T|U|P| |l|e|t| 
|g|:|j|a|v|a|_|h|i|g|h|l|i|g|h|t|_|g|e|n|e|r|i|c|s| |=| |1| +0#0000000&@23
+|/+0#0000e05&@1| |V|I|M|_|T|E|S|T|_|S|E|T|U|P| |h|i| |l|i|n|k| 
|j|a|v|a|G|e|n|e|r|i|c|s|C|1| |T|o|d|o| +0#0000000&@29
+|/+0#0000e05&@1| |V|I|M|_|T|E|S|T|_|S|E|T|U|P| |h|i| |l|i|n|k| 
|j|a|v|a|G|e|n|e|r|i|c|s|C|2| |E|r@1|o|r| +0#0000000&@28
+@75
+|i+0#e000e06&|m|p|o|r|t| 
+0#0000000&|j|a|v|a|.|m|a|t|h|.|B|i|g|I|n|t|e|g|e|r|;| @46
+|i+0#e000e06&|m|p|o|r|t| 
+0#0000000&|j|a|v|a|.|u|t|i|l|.|f|u|n|c|t|i|o|n|.|C|o|n|s|u|m|e|r|;| @39
+|i+0#e000e06&|m|p|o|r|t| 
+0#0000000&|j|a|v|a|.|u|t|i|l|.|f|u|n|c|t|i|o|n|.|F|u|n|c|t|i|o|n|;| @39
+|i+0#e000e06&|m|p|o|r|t| 
+0#0000000&|j|a|v|a|.|u|t|i|l|.|f|u|n|c|t|i|o|n|.|L|o|n|g|F|u|n|c|t|i|o|n|;| @35
+|i+0#e000e06&|m|p|o|r|t| 
+0#0000000&|j|a|v|a|.|u|t|i|l|.|f|u|n|c|t|i|o|n|.|P|r|e|d|i|c|a|t|e|;| @38
+@75
+|c+0#00e0003&|l|a|s@1| 
+0#0000000&|G+0#0000001#ffff4012|e|n|e|r|i|c|s|T|e|s|t|s|<|T+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| +0#0000000&|N|u|m|b|e|r| |&| 
|C+0#ffffff16#ff404010|o|m|p|a|r|a|b|l|e|<|?+0#0000000#ffffff0| 
|s+0#00e0003&|u|p|e|r| +0#0000000&|T|>+0#ffffff16#ff404010|,+0#0000000#ffffff0| 
|U|>+0#0000001#ffff4012| +0#0000000#ffffff0@10
+|{| @2|/+0#0000e05&@1| |J|D|K| |2|1|+|.| +0#0000000&@59
+@4|s+0#00e0003&|t|a|t|i|c| +0#0000000&|f+0#4040ff13&|i|n|a|l| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|O+0#0000000#ffffff0|b|j|e|c|t|,|
 |O|b|j|e|c|t|>+0#ffffff16#ff404010|,+0#0000000#ffffff0| 
|O|b|j|e|c|t|>+0#0000001#ffff4012| +0#0000000#ffffff0|P|A|R|T|I|A|L| |=| @5
+@24|G|e|n|e|r|i|c|s|T|e|s|t|s|.|y|0|(|)|;| @31
+@4|s+0#00e0003&|t|a|t|i|c| +0#0000000&|f+0#4040ff13&|i|n|a|l| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|B+0#0000000#ffffff0|i|g|I|n|t|e|g|e|r|,|
 |B|i|g|I|n|t|e|g|e|r|>+0#0000001#ffff4012| 
+0#0000000#ffffff0|F|A|C|T|O|R|I|A|L|_|2|0@2| |=| @8
+@16|G|e|n|e|r|i|c|s|T|e|s|t|s|.|<|B|i|g|I|n|t|e|g|e|r|,| 
|B|i|g|I|n|t|e|g|e|r|>|y|1|(|)| @16
+@8|.|a|p@1|l|y|(|f+0#00e0e07&| |-|>| +0#0000000&|x+0#00e0e07&| |-|>| 
+0#0000000&|(|x|.|c|o|m|p|a|r|e|T|o|(|B|i|g|I|n|t|e|g|e|r|.|O|N|E|)| |<| 
|1+0#e000002&|)+0#0000000&| @16
+@12|?| |B|i|g|I|n|t|e|g|e|r|.|O|N|E| @46
+@57|1|,|1| @10|T|o|p| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_01.dump 
b/runtime/syntax/testdir/dumps/java_generics_01.dump
new file mode 100644
index 000000000..b5650c7f4
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_01.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@3|s+0#00e0003&|t|a|t|i|c| +0#0000000&|f+0#4040ff13&|i|n|a|l| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|O+0#0000000#ffffff0|b|j|e|c|t|,|
 |O|b|j|e|c|t|>+0#ffffff16#ff404010|,+0#0000000#ffffff0| 
|O|b|j|e|c|t|>+0#0000001#ffff4012| +0#0000000#ffffff0|P|A|R|T|I|A|L| |=| @5
+@24|G|e|n|e|r|i|c|s|T|e|s|t|s|.|y|0|(|)|;| @31
+@4|s+0#00e0003&|t|a|t|i|c| +0#0000000&|f+0#4040ff13&|i|n|a|l| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|B+0#0000000#ffffff0|i|g|I|n|t|e|g|e|r|,|
 |B|i|g|I|n|t|e|g|e|r|>+0#0000001#ffff4012| 
+0#0000000#ffffff0|F|A|C|T|O|R|I|A|L|_|2|0@2| |=| @8
+@16|G|e|n|e|r|i|c|s|T|e|s|t|s|.|<|B|i|g|I|n|t|e|g|e|r|,| 
|B|i|g|I|n|t|e|g|e|r|>|y|1|(|)| @16
+@8|.|a|p@1|l|y|(|f+0#00e0e07&| |-|>| +0#0000000&|x+0#00e0e07&| |-|>| 
+0#0000000&|(|x|.|c|o|m|p|a|r|e|T|o|(|B|i|g|I|n|t|e|g|e|r|.|O|N|E|)| |<| 
|1+0#e000002&|)+0#0000000&| @16
+@12>?| |B|i|g|I|n|t|e|g|e|r|.|O|N|E| @46
+@12|:| 
|x|.|m|u|l|t|i|p|l|y|(|f|.|a|p@1|l|y|(|x|.|s|u|b|t|r|a|c|t|(|B|i|g|I|n|t|e|g|e|r|.|O|N|E|)@3|;|
 @11
+@75
+| +0#00e0e07&@3|s+0#00e0003&|t|a|t|i|c| +0#00e0e07&|<|T|1|>| 
|Y+0#0000001#ffff4012|0|<|T+0#0000000#ffffff0|1|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|y|0|(|)| +0#0000000&@47
+@4|{| @69
+@8|r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|(+0#00e0e07&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,+0#00e0e07&|
 |T+0#0000000&|1|>+0#0000001#ffff4012| +0#00e0e07#ffffff0|f|)| |-|>| 
+0#0000000&|f|.|a|p@1|l|y|(| @27
+@20|G|e|n|e|r|i|c|s|T|e|s|t|s|.|<|T|1|>|y|0|(|)| @32
+@24|.|a|p@1|l|y|(|f|)@1|;| @39
+@4|}| @69
+@75
+| +0#00e0e07&@3|s+0#00e0003&|t|a|t|i|c| +0#00e0e07&|<|T|1|,| |T|2|>| 
|Y+0#0000001#ffff4012|1|<|T+0#0000000#ffffff0|1|,+0#00e0e07&| 
|T+0#0000000&|2|>+0#0000001#ffff4012| +0#00e0e07#ffffff0|y|1|(|)| +0#0000000&@39
+@4|{| @69
+@8|r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|(+0#00e0e07&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,+0#00e0e07&|
 |T+0#0000000&|2|>+0#ffffff16#ff404010|,+0#00e0e07#ffffff0| 
|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,+0#00e0e07&| 
|T+0#0000000&|2|>+0#ffffff16#ff404010|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|f|)| |-|>| +0#0000000&@8
+@12|(+0#00e0e07&|T|1| |x|)| |-|>| 
+0#0000000&|f|.|a|p@1|l|y|(|G|e|n|e|r|i|c|s|T|e|s|t|s|.|<|T|1|,| 
|T|2|>|y|1|(|)| @18
+@57|1|9|,|4|-|1|3| @6|1|0|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_02.dump 
b/runtime/syntax/testdir/dumps/java_generics_02.dump
new file mode 100644
index 000000000..af51ce3f8
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_02.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@11|(+0#00e0e07&|T|1| |x|)| |-|>| 
+0#0000000&|f|.|a|p@1|l|y|(|G|e|n|e|r|i|c|s|T|e|s|t|s|.|<|T|1|,| 
|T|2|>|y|1|(|)| @18
+@24|.|a|p@1|l|y|(|f|)@1| @40
+@16|.|a|p@1|l|y|(|x|)|;| @48
+@4|}| @69
+@75
+@4>s+0#00e0003&|t|a|t|i|c|<+0#0000000&|T|>| |v+0#00e0003&|o|i|d| 
+0#0000000&|n|o|O|p|(|T| |d|u|m@1|y|)| |{| |}| @38
+@75
+@4|i+0#00e0003&|n|t|e|r|f|a|c|e| +0#0000000&|a|l|p|h|a|<|T|>| |{| |}| @48
+@75
+@4|i+0#00e0003&|n|t|e|r|f|a|c|e| 
+0#0000000&|Y+0#0000001#ffff4012|0|<|T+0#0000000#ffffff0|1|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,|
 |T|1|>+0#ffffff16#ff404010|,+0#0000000#ffffff0| |T|1|>+0#0000001#ffff4012| 
+0#0000000#ffffff0|{| |}| @11
+@75
+@4|i+0#00e0003&|n|t|e|r|f|a|c|e| 
+0#0000000&|Y+0#0000001#ffff4012|1|<|T+0#0000000#ffffff0|1|,| 
|T|2|>+0#0000001#ffff4012| +0#0000000#ffffff0|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,|
 |T|2|>+0#0000001#ffff4012|,+0#0000000#ffffff0| @6
+@20|F+0#0000001#ffff4012|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,| 
|T|2|>+0#0000001#ffff4012|>+0#ffffff16#ff404010|,+0#0000000#ffffff0| @36
+@20|F+0#ffffff16#ff404010|u|n|c|t|i|o|n|<|T+0#0000000#ffffff0|1|,| 
|T|2|>+0#ffffff16#ff404010|>+0#0000001#ffff4012| +0#0000000#ffffff0|{| |}| @33
+@75
+@4|i+0#00e0003&|n|t|e|r|f|a|c|e| 
+0#0000000&|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|I+0#0000001#ffff4012|t|e|r|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@28
+@4|{| @69
+| +0#00e0e07&@7|b+0#00e0003&|o@1|l|e|a|n| 
+0#00e0e07&|i|s|E|m|p|t|y|(|)|;+0#0000000&| @48
+| +0#00e0e07&@7|E| |p|e@1|k|(|)|;+0#0000000&| @57
+@57|3|7|,|2|-|5| @7|2|5|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_03.dump 
b/runtime/syntax/testdir/dumps/java_generics_03.dump
new file mode 100644
index 000000000..3e4f6c869
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_03.dump
@@ -0,0 +1,20 @@
+| +0#00e0e07#ffffff0@7|E| |p|e@1|k|(|)|;+0#0000000&| @57
+| +0#00e0e07&@7|E| |p|o|p|(|)|;+0#0000000&| @58
+| 
+0#00e0e07&@7|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 
+0#00e0e07#ffffff0|p|o|p|A|l@1|(|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|?+0#0000000#ffffff0|
 +0#00e0e07&|s+0#00e0003&|u|p|e|r| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|e|l|e|m|e|n|t|s|)|;+0#0000000&| @15
+| 
+0#00e0e07&@7|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 
+0#00e0e07#ffffff0|p|o|p|S|o|m|e|(|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|?+0#0000000#ffffff0|
 +0#00e0e07&|s+0#00e0003&|u|p|e|r| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|e|l|e|m|e|n|t|s|,| +0#0000000&@15
+| +0#00e0e07&@19|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|?+0#0000000#ffffff0| 
+0#00e0e07&|s+0#00e0003&|u|p|e|r| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|f|i|l|t|e|r|)|;+0#0000000&| @25
+| 
+0#00e0e07&@7>S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#00e0e07#ffffff0|p|u|s|h|(|E| |e|l|e|m|e|n|t|)|;+0#0000000&| @37
+| 
+0#00e0e07&@7|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 
+0#00e0e07#ffffff0|p|u|s|h|A|l@1|(|I+0#0000001#ffff4012|t|e|r|a|b|l|e|<|?+0#0000000#ffffff0|
 +0#00e0e07&|e+0#00e0003&|x|t|e|n|d|s| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|e|l|e|m|e|n|t|s|)|;+0#0000000&| @13
+| 
+0#00e0e07&@7|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 
+0#00e0e07#ffffff0|p|u|s|h|S|o|m|e|(|I+0#0000001#ffff4012|t|e|r|a|b|l|e|<|?+0#0000000#ffffff0|
 +0#00e0e07&|e+0#00e0003&|x|t|e|n|d|s| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|e|l|e|m|e|n|t|s|,| +0#0000000&@13
+| +0#00e0e07&@19|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|?+0#0000000#ffffff0| 
+0#00e0e07&|s+0#00e0003&|u|p|e|r| 
+0#00e0e07&|E+0#0000000&|>+0#0000001#ffff4012| 
+0#00e0e07#ffffff0|f|i|l|t|e|r|)|;+0#0000000&| @25
+| 
+0#00e0e07&@7|S+0#0000001#ffff4012|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#0000001#ffff4012|
 
+0#00e0e07#ffffff0|w|i|n|d|(|C+0#0000001#ffff4012|o|n|s|u|m|e|r|<|?+0#0000000#ffffff0|
 +0#00e0e07&|s+0#00e0003&|u|p|e|r| 
+0#00e0e07&|S+0#ffffff16#ff404010|t|a|c|k|a|b|l|e|<|E+0#0000000#ffffff0|>+0#ffffff16#ff404010|>+0#0000001#ffff4012|
 +0#00e0e07#ffffff0|a|c|t|i|o|n|)|;+0#0000000&| @9
+@4|}| @69
+@75
+@4|s+0#4040ff13&|e|a|l|e|d| +0#0000000&|i+0#00e0003&|n|t|e|r|f|a|c|e| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| +0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012| 
+0#0000000#ffffff0@32
+@4|{| @69
+| +0#00e0e07&@7|i+0#00e0003&|n|t| +0#00e0e07&|r|a|d|i|x|(|)|;+0#0000000&| @54
+| +0#00e0e07&@7|N| |v|a|l|u|e|(|)|;+0#0000000&| @56
+@4|}| @69
+@75
+@4|r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|B+0#0000001#ffff4012|i|n|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012|(+0#0000000#ffffff0|N| 
|v|a|l|u|e|)| |i+0#00e0003&|m|p|l|e|m|e|n|t|s| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@15
+@57|5@1|,|3|-|9| @7|4|0|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_04.dump 
b/runtime/syntax/testdir/dumps/java_generics_04.dump
new file mode 100644
index 000000000..2e0203766
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_04.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@3|r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|B+0#0000001#ffff4012|i|n|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012|(+0#0000000#ffffff0|N| 
|v|a|l|u|e|)| |i+0#00e0003&|m|p|l|e|m|e|n|t|s| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@15
+@4|{| @69
+| +0#00e0e07&@7|p+0#00e0003&|u|b|l|i|c| +0#00e0e07&|i+0#00e0003&|n|t| 
+0#00e0e07&|r|a|d|i|x|(|)| +0#0000000&|{| |r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|2+0#e000002&|;+0#0000000&| |}| @34
+@4|}| @69
+@75
+@4>r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|D+0#0000001#ffff4012|e|c|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012|(+0#0000000#ffffff0|N| 
|v|a|l|u|e|)| |i+0#00e0003&|m|p|l|e|m|e|n|t|s| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@15
+@4|{| @69
+| +0#00e0e07&@7|p+0#00e0003&|u|b|l|i|c| +0#00e0e07&|i+0#00e0003&|n|t| 
+0#00e0e07&|r|a|d|i|x|(|)| +0#0000000&|{| |r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|1+0#e000002&|0|;+0#0000000&| |}| @33
+@4|}| @69
+@75
+@4|r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|H+0#0000001#ffff4012|e|x|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012|(+0#0000000#ffffff0|N| 
|v|a|l|u|e|)| |i+0#00e0003&|m|p|l|e|m|e|n|t|s| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@15
+@4|{| @69
+| +0#00e0e07&@7|p+0#00e0003&|u|b|l|i|c| +0#00e0e07&|i+0#00e0003&|n|t| 
+0#00e0e07&|r|a|d|i|x|(|)| +0#0000000&|{| |r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|1+0#e000002&|6|;+0#0000000&| |}| @33
+@4|}| @69
+@75
+@4|r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|O+0#0000001#ffff4012|c|t|<|N+0#0000000#ffffff0| 
|e+0#00e0003&|x|t|e|n|d|s| 
+0#0000000&|N|u|m|b|e|r|>+0#0000001#ffff4012|(+0#0000000#ffffff0|N| 
|v|a|l|u|e|)| |i+0#00e0003&|m|p|l|e|m|e|n|t|s| 
+0#0000000&|N+0#0000001#ffff4012|u|m|<|N+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0@15
+@4|{| @69
+| +0#00e0e07&@7|p+0#00e0003&|u|b|l|i|c| +0#00e0e07&|i+0#00e0003&|n|t| 
+0#00e0e07&|r|a|d|i|x|(|)| +0#0000000&|{| |r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|8+0#e000002&|;+0#0000000&| |}| @34
+@4|}| @69
+@57|7|3|,|2|-|5| @7|5@1|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_05.dump 
b/runtime/syntax/testdir/dumps/java_generics_05.dump
new file mode 100644
index 000000000..7e51e7d64
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_05.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@3|}| @69
+@75
+| +0#00e0e07&@3|s+0#00e0003&|t|a|t|i|c| 
+0#00e0e07&|N+0#0000001#ffff4012|u|m|<|L+0#0000000#ffffff0|o|n|g|>+0#0000001#ffff4012|
 +0#00e0e07#ffffff0|f|r|o|m|D|e|c|i|m|a|l|(|l+0#00e0003&|o|n|g| 
+0#00e0e07&|x|,| |i+0#00e0003&|n|t| +0#00e0e07&|r|a|d|i|x|)| +0#0000000&@23
+@4|{| @69
+@8|r+0#00e0003&|e|c|o|r|d| 
+0#0000000&|P|a|i|r|(|L+0#0000001#ffff4012|o|n|g|F|u|n|c|t|i|o|n|<|N+0#ffffff16#ff404010|u|m|<|L+0#0000000#ffffff0|o|n|g|>+0#ffffff16#ff404010|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|a|,| @28
+@20>L+0#0000001#ffff4012|o|n|g|F|u|n|c|t|i|o|n|<|S+0#0000000#ffffff0|t|r|i|n|g|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|b|)| |{| |}| @27
+@8|f+0#4040ff13&|i|n|a|l| +0#0000000&|P|a|i|r| |p| |=| 
|s+0#af5f00255&|w|i|t|c|h| +0#0000000&|(|r|a|d|i|x|)| |{| @35
+@12|c+0#af5f00255&|a|s|e| +0#0000000&|2+0#e000002&| +0#0000000&|-|>| 
|n+0#af5f00255&|e|w| 
+0#0000000&|P|a|i|r|(|B|i|n|:@1|n+0#af5f00255&|e|w|,+0#0000000&| 
|L|o|n|g|:@1|t|o|B|i|n|a|r|y|S|t|r|i|n|g|)|;| @11
+@12|c+0#af5f00255&|a|s|e| +0#0000000&|8+0#e000002&| +0#0000000&|-|>| 
|n+0#af5f00255&|e|w| 
+0#0000000&|P|a|i|r|(|O|c|t|:@1|n+0#af5f00255&|e|w|,+0#0000000&| 
|L|o|n|g|:@1|t|o|O|c|t|a|l|S|t|r|i|n|g|)|;| @12
+@12|c+0#af5f00255&|a|s|e| +0#0000000&|1+0#e000002&|6| +0#0000000&|-|>| 
|n+0#af5f00255&|e|w| 
+0#0000000&|P|a|i|r|(|H|e|x|:@1|n+0#af5f00255&|e|w|,+0#0000000&| 
|L|o|n|g|:@1|t|o|H|e|x|S|t|r|i|n|g|)|;| @13
+@12|d+0#af5f00255&|e|f|a|u|l|t| +0#0000000&|-|>| |n+0#af5f00255&|e|w| 
+0#0000000&|P|a|i|r|(|D|e|c|:@1|n+0#af5f00255&|e|w|,+0#0000000&| @33
+@24|y+0#00e0e07&| |-|>| +0#0000000&|L|o|n|g|.|t|o|S|t|r|i|n|g|(|y|)@1|;| @27
+@8|}|;| @64
+@8|r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|p|.|a|(|)|.|a|p@1|l|y|(|L|o|n|g|.|p|a|r|s|e|L|o|n|g|(|p|.|b|(|)|.|a|p@1|l|y|(|x|)|,|
 |r|a|d|i|x|)@1|;| @8
+@4|}| @69
+@75
+| +0#00e0e07&@3|s+0#00e0003&|t|a|t|i|c| +0#00e0e07&|l+0#00e0003&|o|n|g| 
+0#00e0e07&|t|o|D|e|c|i|m|a|l|(|N+0#0000001#ffff4012|u|m|<|L+0#0000000#ffffff0|o|n|g|>+0#0000001#ffff4012|
 +0#00e0e07#ffffff0|x|)| +0#0000000&@36
+@4|{| @69
+@8|r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|L|o|n|g|.|p|a|r|s|e|L|o|n|g|(|s+0#af5f00255&|w|i|t|c|h| 
+0#0000000&|(|x|)| |{| @32
+@57|9|1|,|6|-|2|1| @6|7|0|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_06.dump 
b/runtime/syntax/testdir/dumps/java_generics_06.dump
new file mode 100644
index 000000000..de1c46c27
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_06.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@7|r+0#af5f00255&|e|t|u|r|n| 
+0#0000000&|L|o|n|g|.|p|a|r|s|e|L|o|n|g|(|s+0#af5f00255&|w|i|t|c|h| 
+0#0000000&|(|x|)| |{| @32
+@12|c+0#af5f00255&|a|s|e| 
+0#0000000&|B+0#0000001#ffff4012|i|n|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012|(+0#0000000#ffffff0|L|o|n|g|
 |b|)| |-|>| |L|o|n|g|.|t|o|B|i|n|a|r|y|S|t|r|i|n|g|(|b|)|;| @16
+@12|c+0#af5f00255&|a|s|e| 
+0#0000000&|O+0#0000001#ffff4012|c|t|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012|(+0#0000000#ffffff0|L|o|n|g|
 |o|)| |-|>| |L|o|n|g|.|t|o|O|c|t|a|l|S|t|r|i|n|g|(|o|)|;| @17
+@12|c+0#af5f00255&|a|s|e| 
+0#0000000&|H+0#0000001#ffff4012|e|x|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012|(+0#0000000#ffffff0|L|o|n|g|
 |h|)| |-|>| |L|o|n|g|.|t|o|H|e|x|S|t|r|i|n|g|(|h|)|;| @19
+@12|d+0#af5f00255&|e|f|a|u|l|t| +0#0000000&|-|>| 
|L|o|n|g|.|t|o|S|t|r|i|n|g|(|x|.|v|a|l|u|e|(|)@1|;| @26
+@8>}|,| |x|.|r|a|d|i|x|(|)@1|;| @52
+@4|}| @69
+@75
+@4|@+0#e000e06&|j|a|v|a|.|l|a|n|g|.|a|n@1|o|t|a|t|i|o|n|.|T|a|r|g|e|t|(| 
+0#0000000&@41
+@16|j|a|v|a|.|l|a|n|g|.|a|n@1|o|t|a|t|i|o|n|.|E|l|e|m|e|n|t|T|y|p|e|.|T|Y|P|E|_|U|S|E|)+0#e000e06&|
 +0#0000000&@16
+@4|@+0#00e0003&|i|n|t|e|r|f|a|c|e| +0#0000000&|T|a|g@1|a|b|l|e| @51
+@4|{| @69
+| +0#00e0e07&@7|S|t|r|i|n|g| |v|a|l|u|e|(|)| 
+0#0000000&|d+0#4040ff13&|e|f|a|u|l|t| +0#0000000&|"+0#e000002&@1|;+0#0000000&| 
@40
+@4|}| @69
+@75
+@4|{| @69
+@8|i+0#00e0003&|n|t| +0#0000000&|N| |=| |0+0#e000002&|,+0#0000000&| |X| |=| 
|1+0#e000002&|,+0#0000000&| |Y| |=| |2+0#e000002&|;+0#0000000&| @42
+@8|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|T+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|f| |=| 
|y+0#00e0e07&|-|>|N+0#0000000&|<|y|.|i|n|t|V|a|l|u|e|(|)|;| @31
+@8|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|T+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|g| |=| 
|y+0#00e0e07&|-|>|X+0#0000001#ffff4012|<|N+0#0000000#ffffff0|&@1|(|I|n|t|e|g|e|r|)|y|>+0#0000001#ffff4012|N+0#0000000#ffffff0|;|
 @28
+@57|1|0|9|,|3|-|9| @6|8|5|%| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_07.dump 
b/runtime/syntax/testdir/dumps/java_generics_07.dump
new file mode 100644
index 000000000..fffbf040a
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_07.dump
@@ -0,0 +1,20 @@
+| 
+0&#ffffff0@7|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|T+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|g| |=| 
|y+0#00e0e07&|-|>|X+0#0000001#ffff4012|<|N+0#0000000#ffffff0|&@1|(|I|n|t|e|g|e|r|)|y|>+0#0000001#ffff4012|N+0#0000000#ffffff0|;|
 @28
+@8|b+0#00e0003&|o@1|l|e|a|n|[+0#0000000&|]| |b@1| |=| |{| @50
+@12|X+0#0000001#ffff4012|<|N+0#0000000#ffffff0||@1|N|>+0#0000001#ffff4012|Y+0#0000000#ffffff0|,|
 |X| |<| |Y|,| |X| |<|Y|,| |X| |<|(|Y|)|,| |X|<|(|Y|)|,| |(|X|)|<|Y|,| @18
+@12|D|o|u|b|l|e|.|i|s|F|i|n|i|t|e|(|X|<@1|Y|)|,| @40
+@12|X|<|=|Y|,| 
|X|<|(|i+0#00e0003&|n|t|)+0#0000000&|(|b+0#00e0003&|y|t|e|)+0#0000000&|Y|,| 
|X|<|~|Y|,| |X|<|-|Y|,| |X|<|+|Y|,| @23
+@8>}|;| @64
+@8|C+0#0000001#ffff4012|l|a|s@1|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012| 
+0#0000000#ffffff0|k|l|a|s@1| |=| 
|G|e|n|e|r|i|c|s|T|e|s|t|s|.|c+0#00e0003&|l|a|s@1|;+0#0000000&| @29
+@8|C+0#0000001#ffff4012|l|a|s@1|<| 
+0#0000000#ffffff0|j+0#ffffff16#ff404010|a|v|a|.|l|a|n|g|.|C|l|a|s@1|<|@+0#e000e06#ffffff0|T|a|g@1|a|b|l|e|(|"+0#e000002&|<|>|"|)+0#e000e06&|i+0#00e0003&|n|t|[+0#0000000&|]|[|]|>+0#ffffff16#ff404010|
 +0#0000000#ffffff0|[+0#ffffff16#ff404010|]| 
+0#0000000#ffffff0|[+0#ffffff16#ff404010|]| 
+0#0000000#ffffff0|>+0#0000001#ffff4012| +0#0000000#ffffff0@12
+@8|[+0#0000001#ffff4012| +0#0000000#ffffff0|]+0#0000001#ffff4012| 
+0#0000000#ffffff0|[+0#0000001#ffff4012| 
+0#0000000#ffffff0|]+0#0000001#ffff4012| +0#0000000#ffffff0|$| |[| |]| |[| 
|]|;| @48
+@8|i+0#af5f00255&|f| +0#0000000&|(|f+0#e000002&|a|l|s|e|)+0#0000000&| |{| 
|n+0#af5f00255&|e|w| +0#0000000&|G|e|n|e|r|i|c|s|T|e|s|t|s|<|>|(|)|;| |}| @29
+@8|a|l|p|h|a|<|?|>| |a|o|;| @54
+@8|a|l|p|h|a|<|U|>| |a|u|;| @54
+@8|a|l|p|h|a|<|a|l|p|h|a|<|U|>@1| |a@1|u|;| @46
+@8|a|l|p|h|a|<|Y+0#0000001#ffff4012|0|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012|>+0#0000000#ffffff0|
 |a|y|0|o|;| @48
+@8|a|l|p|h|a|<|Y+0#0000001#ffff4012|0|<|U+0#0000000#ffffff0|>+0#0000001#ffff4012|>+0#0000000#ffffff0|
 |a|y|0|u|;| @48
+@8|Y|0|<|a|l|p|h|a|<|?|>@1| |y|0|a|o|;| @48
+@8|Y|0|<|a|l|p|h|a|<|U|>@1| |y|0|a|u|;| @48
+@4|}| @69
+|}| @73
+@57|1|2|7|,|3|-|9| @6|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/java_generics_99.dump 
b/runtime/syntax/testdir/dumps/java_generics_99.dump
new file mode 100644
index 000000000..a7dff098f
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/java_generics_99.dump
@@ -0,0 +1,20 @@
+| 
+0&#ffffff0@7|P+0#0000001#ffff4012|r|e|d|i|c|a|t|e|<|T+0#0000000#ffffff0|>+0#0000001#ffff4012|
 +0#0000000#ffffff0|g| |=| 
|y+0#00e0e07&|-|>|X+0#0000001#ffff4012|<|N+0#0000000#ffffff0|&@1|(|I|n|t|e|g|e|r|)|y|>+0#0000001#ffff4012|N+0#0000000#ffffff0|;|
 @28
+@8|b+0#00e0003&|o@1|l|e|a|n|[+0#0000000&|]| |b@1| |=| |{| @50
+@12|X+0#0000001#ffff4012|<|N+0#0000000#ffffff0||@1|N|>+0#0000001#ffff4012|Y+0#0000000#ffffff0|,|
 |X| |<| |Y|,| |X| |<|Y|,| |X| |<|(|Y|)|,| |X|<|(|Y|)|,| |(|X|)|<|Y|,| @18
+@12|D|o|u|b|l|e|.|i|s|F|i|n|i|t|e|(|X|<@1|Y|)|,| @40
+@12|X|<|=|Y|,| 
|X|<|(|i+0#00e0003&|n|t|)+0#0000000&|(|b+0#00e0003&|y|t|e|)+0#0000000&|Y|,| 
|X|<|~|Y|,| |X|<|-|Y|,| |X|<|+|Y|,| @23
+@8|}|;| @64
+@8|C+0#0000001#ffff4012|l|a|s@1|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012| 
+0#0000000#ffffff0|k|l|a|s@1| |=| 
|G|e|n|e|r|i|c|s|T|e|s|t|s|.|c+0#00e0003&|l|a|s@1|;+0#0000000&| @29
+@8|C+0#0000001#ffff4012|l|a|s@1|<| 
+0#0000000#ffffff0|j+0#ffffff16#ff404010|a|v|a|.|l|a|n|g|.|C|l|a|s@1|<|@+0#e000e06#ffffff0|T|a|g@1|a|b|l|e|(|"+0#e000002&|<|>|"|)+0#e000e06&|i+0#00e0003&|n|t|[+0#0000000&|]|[|]|>+0#ffffff16#ff404010|
 +0#0000000#ffffff0|[+0#ffffff16#ff404010|]| 
+0#0000000#ffffff0|[+0#ffffff16#ff404010|]| 
+0#0000000#ffffff0|>+0#0000001#ffff4012| +0#0000000#ffffff0@12
+@8|[+0#0000001#ffff4012| +0#0000000#ffffff0|]+0#0000001#ffff4012| 
+0#0000000#ffffff0|[+0#0000001#ffff4012| 
+0#0000000#ffffff0|]+0#0000001#ffff4012| +0#0000000#ffffff0|$| |[| |]| |[| 
|]|;| @48
+@8|i+0#af5f00255&|f| +0#0000000&|(|f+0#e000002&|a|l|s|e|)+0#0000000&| |{| 
|n+0#af5f00255&|e|w| +0#0000000&|G|e|n|e|r|i|c|s|T|e|s|t|s|<|>|(|)|;| |}| @29
+@8|a|l|p|h|a|<|?|>| |a|o|;| @54
+@8|a|l|p|h|a|<|U|>| |a|u|;| @54
+@8|a|l|p|h|a|<|a|l|p|h|a|<|U|>@1| |a@1|u|;| @46
+@8|a|l|p|h|a|<|Y+0#0000001#ffff4012|0|<|?+0#0000000#ffffff0|>+0#0000001#ffff4012|>+0#0000000#ffffff0|
 |a|y|0|o|;| @48
+@8|a|l|p|h|a|<|Y+0#0000001#ffff4012|0|<|U+0#0000000#ffffff0|>+0#0000001#ffff4012|>+0#0000000#ffffff0|
 |a|y|0|u|;| @48
+@8|Y|0|<|a|l|p|h|a|<|?|>@1| |y|0|a|o|;| @48
+@8|Y|0|<|a|l|p|h|a|<|U|>@1| |y|0|a|u|;| @48
+@4|}| @69
+>}| @73
+@57|1|4|0|,|1| @8|B|o|t| 
diff --git a/runtime/syntax/testdir/input/java_generics.java 
b/runtime/syntax/testdir/input/java_generics.java
new file mode 100644
index 000000000..c9b001a40
--- /dev/null
+++ b/runtime/syntax/testdir/input/java_generics.java
@@ -0,0 +1,140 @@
+// VIM_TEST_SETUP let g:java_highlight_functions = 'style'
+// VIM_TEST_SETUP let g:java_highlight_generics = 1
+// VIM_TEST_SETUP hi link javaGenericsC1 Todo
+// VIM_TEST_SETUP hi link javaGenericsC2 Error
+
+import java.math.BigInteger;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.LongFunction;
+import java.util.function.Predicate;
+
+class GenericsTests<T extends Number & Comparable<? super T>, U>
+{      // JDK 21+.
+       static final Function<Function<Object, Object>, Object> PARTIAL =
+                                               GenericsTests.y0();
+       static final Function<BigInteger, BigInteger> FACTORIAL_2000 =
+                               GenericsTests.<BigInteger, BigInteger>y1()
+               .apply(f -> x -> (x.compareTo(BigInteger.ONE) < 1)
+                       ? BigInteger.ONE
+                       : x.multiply(f.apply(x.subtract(BigInteger.ONE))));
+
+       static <T1> Y0<T1> y0()
+       {
+               return (Function<T1, T1> f) -> f.apply(
+                                       GenericsTests.<T1>y0()
+                                               .apply(f));
+       }
+
+       static <T1, T2> Y1<T1, T2> y1()
+       {
+               return (Function<Function<T1, T2>, Function<T1, T2>> f) ->
+                       (T1 x) -> f.apply(GenericsTests.<T1, T2>y1()
+                                               .apply(f))
+                               .apply(x);
+       }
+
+       static<T> void noOp(T dummy) { }
+
+       interface alpha<T> { }
+
+       interface Y0<T1> extends Function<Function<T1, T1>, T1> { }
+
+       interface Y1<T1, T2> extends Function<Function<Function<T1, T2>,
+                                       Function<T1, T2>>,
+                                       Function<T1, T2>> { }
+
+       interface Stackable<E> extends Iterable<E>
+       {
+               boolean isEmpty();
+               E peek();
+               E pop();
+               Stackable<E> popAll(Stackable<? super E> elements);
+               Stackable<E> popSome(Stackable<? super E> elements,
+                                       Predicate<? super E> filter);
+               Stackable<E> push(E element);
+               Stackable<E> pushAll(Iterable<? extends E> elements);
+               Stackable<E> pushSome(Iterable<? extends E> elements,
+                                       Predicate<? super E> filter);
+               Stackable<E> wind(Consumer<? super Stackable<E>> action);
+       }
+
+       sealed interface Num<N extends Number>
+       {
+               int radix();
+               N value();
+       }
+
+       record Bin<N extends Number>(N value) implements Num<N>
+       {
+               public int radix() { return 2; }
+       }
+
+       record Dec<N extends Number>(N value) implements Num<N>
+       {
+               public int radix() { return 10; }
+       }
+
+       record Hex<N extends Number>(N value) implements Num<N>
+       {
+               public int radix() { return 16; }
+       }
+
+       record Oct<N extends Number>(N value) implements Num<N>
+       {
+               public int radix() { return 8; }
+       }
+
+       static Num<Long> fromDecimal(long x, int radix)
+       {
+               record Pair(LongFunction<Num<Long>> a,
+                                       LongFunction<String> b) { }
+               final Pair p = switch (radix) {
+                       case 2 -> new Pair(Bin::new, Long::toBinaryString);
+                       case 8 -> new Pair(Oct::new, Long::toOctalString);
+                       case 16 -> new Pair(Hex::new, Long::toHexString);
+                       default -> new Pair(Dec::new,
+                                               y -> Long.toString(y));
+               };
+               return p.a().apply(Long.parseLong(p.b().apply(x), radix));
+       }
+
+       static long toDecimal(Num<Long> x)
+       {
+               return Long.parseLong(switch (x) {
+                       case Bin<?>(Long b) -> Long.toBinaryString(b);
+                       case Oct<?>(Long o) -> Long.toOctalString(o);
+                       case Hex<?>(Long h) -> Long.toHexString(h);
+                       default -> Long.toString(x.value());
+               }, x.radix());
+       }
+
+       @java.lang.annotation.Target(
+                               java.lang.annotation.ElementType.TYPE_USE)
+       @interface Taggable
+       {
+               String value() default "";
+       }
+
+       {
+               int N = 0, X = 1, Y = 2;
+               Predicate<T> f = y->N<y.intValue();
+               Predicate<T> g = y->X<N&&(Integer)y>N;
+               boolean[] bb = {
+                       X<N||N>Y, X < Y, X <Y, X <(Y), X<(Y), (X)<Y,
+                       Double.isFinite(X<<Y),
+                       X<=Y, X<(int)(byte)Y, X<~Y, X<-Y, X<+Y,
+               };
+               Class<?> klass = GenericsTests.class;
+               Class< java.lang.Class<@Taggable("<>")int[][]> [] [] >
+               [ ] [ ] $ [ ] [ ];
+               if (false) { new GenericsTests<>(); }
+               alpha<?> ao;
+               alpha<U> au;
+               alpha<alpha<U>> aau;
+               alpha<Y0<?>> ay0o;
+               alpha<Y0<U>> ay0u;
+               Y0<alpha<?>> y0ao;
+               Y0<alpha<U>> y0au;
+       }
+}

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sKNFU-007QPb-4n%40256bit.org.

Raspunde prin e-mail lui