From 4ec7535c82a384a8149720e48d038e6e622478fa Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Sat, 3 Apr 2021 11:35:15 +0200 Subject: [PATCH] Java: Improved generics (#2812) --- components/prism-java.js | 2 +- components/prism-java.min.js | 2 +- tests/languages/java/generics_feature.test | 200 +++++++++++++++++---- 3 files changed, 168 insertions(+), 36 deletions(-) diff --git a/components/prism-java.js b/components/prism-java.js index 16a3346ffd..86f1844c5f 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 21a5b50534..26a914f2a6 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+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//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+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//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 12d9fb6231..7944a7ee8e 100644 --- a/tests/languages/java/generics_feature.test +++ b/tests/languages/java/generics_feature.test @@ -2,19 +2,30 @@ public class Solo {} Solo val = new Solo<>(); Duo dual = new Duo(12.2585, 'C'); +List list +List nums = ints; +List list +Entry pair = Entry.twice("Hello"); + +public class Entry {} +class D {} + +public void throwMeConditional(boolean conditional, T exception) throws T {} + + T instantiateElementType(List 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 dual = new Duo(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 dual = new Duo(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 dual = new Duo(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", "}"] ] ----------------------------------------------------