Commit 4ec7535c82a384a8149720e48d038e6e622478fa

Michael Schmidt 2021-04-03T11:35:15

Java: Improved generics (#2812)

diff --git a/components/prism-java.js b/components/prism-java.js
index 16a3346..86f1844 100644
--- a/components/prism-java.js
+++ b/components/prism-java.js
@@ -62,7 +62,7 @@
 			alias: 'punctuation'
 		},
 		'generics': {
-			pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,
+			pattern: /<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,
 			inside: {
 				'class-name': className,
 				'keyword': keywords,
diff --git a/components/prism-java.min.js b/components/prism-java.min.js
index 21a5b50..26a914f 100644
--- a/components/prism-java.min.js
+++ b/components/prism-java.min.js
@@ -1 +1 @@
-!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",a={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{"class-name":[a,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=())])"),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(\:\:\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(/<keyword>/g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism);
\ No newline at end of file
+!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",a={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{"class-name":[a,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=())])"),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(\:\:\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(/<keyword>/g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism);
\ No newline at end of file
diff --git a/tests/languages/java/generics_feature.test b/tests/languages/java/generics_feature.test
index 12d9fb6..7944a7e 100644
--- a/tests/languages/java/generics_feature.test
+++ b/tests/languages/java/generics_feature.test
@@ -2,19 +2,30 @@ public class Solo<T extends com.foo.Foo.Bar> {}
 Solo<Integer> val = new Solo<>();
 Duo<Double, Character> dual = new Duo<Double, Character>(12.2585, 'C');
 
+List<?> list
+List<? extends Number> nums = ints;
+List<? super Integer> list
+Entry<String, String> pair = Entry.<String>twice("Hello");
+
+public class Entry<KeyType, ValueType> {}
+class D <T extends A & B & C> {}
+
+public <T extends Throwable> void throwMeConditional(boolean conditional, T exception) throws T {}
+
+<T> T instantiateElementType(List<T> arg) {}
+
+// not generics
+if (a<6&&b>6){}
+
 ----------------------------------------------------
 
 [
 	["keyword", "public"],
 	["keyword", "class"],
-	["class-name", [
-		"Solo"
-	]],
+	["class-name", ["Solo"]],
 	["generics", [
 		["punctuation", "<"],
-		["class-name", [
-			"T"
-		]],
+		["class-name", ["T"]],
 		["keyword", "extends"],
 		["class-name", [
 			["namespace", [
@@ -32,22 +43,16 @@ Duo<Double, Character> dual = new Duo<Double, Character>(12.2585, 'C');
 	["punctuation", "{"],
 	["punctuation", "}"],
 
-	["class-name", [
-		"Solo"
-	]],
+	["class-name", ["Solo"]],
 	["generics", [
 		["punctuation", "<"],
-		["class-name", [
-			"Integer"
-		]],
+		["class-name", ["Integer"]],
 		["punctuation", ">"]
 	]],
 	" val ",
 	["operator", "="],
 	["keyword", "new"],
-	["class-name", [
-		"Solo"
-	]],
+	["class-name", ["Solo"]],
 	["generics", [
 		["punctuation", "<"],
 		["punctuation", ">"]
@@ -56,35 +61,23 @@ Duo<Double, Character> dual = new Duo<Double, Character>(12.2585, 'C');
 	["punctuation", ")"],
 	["punctuation", ";"],
 
-	["class-name", [
-		"Duo"
-	]],
+	["class-name", ["Duo"]],
 	["generics", [
 		["punctuation", "<"],
-		["class-name", [
-			"Double"
-		]],
+		["class-name", ["Double"]],
 		["punctuation", ","],
-		["class-name", [
-			"Character"
-		]],
+		["class-name", ["Character"]],
 		["punctuation", ">"]
 	]],
 	" dual ",
 	["operator", "="],
 	["keyword", "new"],
-	["class-name", [
-		"Duo"
-	]],
+	["class-name", ["Duo"]],
 	["generics", [
 		["punctuation", "<"],
-		["class-name", [
-			"Double"
-		]],
+		["class-name", ["Double"]],
 		["punctuation", ","],
-		["class-name", [
-			"Character"
-		]],
+		["class-name", ["Character"]],
 		["punctuation", ">"]
 	]],
 	["punctuation", "("],
@@ -92,7 +85,146 @@ Duo<Double, Character> dual = new Duo<Double, Character>(12.2585, 'C');
 	["punctuation", ","],
 	["string", "'C'"],
 	["punctuation", ")"],
-	["punctuation", ";"]
+	["punctuation", ";"],
+
+	["class-name", ["List"]],
+	["generics", [
+		["punctuation", "<"],
+		["operator", "?"],
+		["punctuation", ">"]
+	]],
+	" list\r\n",
+
+	["class-name", ["List"]],
+	["generics", [
+		["punctuation", "<"],
+		["operator", "?"],
+		["keyword", "extends"],
+		["class-name", ["Number"]],
+		["punctuation", ">"]
+	]],
+	" nums ",
+	["operator", "="],
+	" ints",
+	["punctuation", ";"],
+
+	["class-name", ["List"]],
+	["generics", [
+		["punctuation", "<"],
+		["operator", "?"],
+		["keyword", "super"],
+		["class-name", ["Integer"]],
+		["punctuation", ">"]
+	]],
+	" list\r\n",
+
+	["class-name", ["Entry"]],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["String"]],
+		["punctuation", ","],
+		["class-name", ["String"]],
+		["punctuation", ">"]
+	]],
+	" pair ",
+	["operator", "="],
+	["class-name", ["Entry"]],
+	["punctuation", "."],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["String"]],
+		["punctuation", ">"]
+	]],
+	["function", "twice"],
+	["punctuation", "("],
+	["string", "\"Hello\""],
+	["punctuation", ")"],
+	["punctuation", ";"],
+
+	["keyword", "public"],
+	["keyword", "class"],
+	["class-name", ["Entry"]],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["KeyType"]],
+		["punctuation", ","],
+		["class-name", ["ValueType"]],
+		["punctuation", ">"]
+	]],
+	["punctuation", "{"],
+	["punctuation", "}"],
+
+	["keyword", "class"],
+	["class-name", ["D"]],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["T"]],
+		["keyword", "extends"],
+		["class-name", ["A"]],
+		["operator", "&"],
+		["class-name", ["B"]],
+		["operator", "&"],
+		["class-name", ["C"]],
+		["punctuation", ">"]
+	]],
+	["punctuation", "{"],
+	["punctuation", "}"],
+
+	["keyword", "public"],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["T"]],
+		["keyword", "extends"],
+		["class-name", ["Throwable"]],
+		["punctuation", ">"]
+	]],
+	["keyword", "void"],
+	["function", "throwMeConditional"],
+	["punctuation", "("],
+	["keyword", "boolean"],
+	" conditional",
+	["punctuation", ","],
+	["class-name", ["T"]],
+	" exception",
+	["punctuation", ")"],
+	["keyword", "throws"],
+	["class-name", ["T"]],
+	["punctuation", "{"],
+	["punctuation", "}"],
+
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["T"]],
+		["punctuation", ">"]
+	]],
+	["class-name", ["T"]],
+	["function", "instantiateElementType"],
+	["punctuation", "("],
+	["class-name", ["List"]],
+	["generics", [
+		["punctuation", "<"],
+		["class-name", ["T"]],
+		["punctuation", ">"]
+	]],
+	" arg",
+	["punctuation", ")"],
+	["punctuation", "{"],
+	["punctuation", "}"],
+
+	["comment", "// not generics"],
+
+	["keyword", "if"],
+	["punctuation", "("],
+	"a",
+	["operator", "<"],
+	["number", "6"],
+	["operator", "&&"],
+	"b",
+	["operator", ">"],
+	["number", "6"],
+	["punctuation", ")"],
+	["punctuation", "{"],
+	["punctuation", "}"]
 ]
 
 ----------------------------------------------------