From 81bd8f0bd1ace55ed40e9a243df89be4deda9758 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Sat, 1 Dec 2018 21:44:17 +0100 Subject: [PATCH] Improve Java (#1474) A bunch of small improvements for the Java language. 1. Class highlighting based on [naming conventions](http://www.oracle.com/technetwork/java/javase/overview/codeconventions-135099.html). Because of these conventions, we know that every name which starts with an uppercase letter and contains some lower case letters afterward is a class, interface or enum. 2. Nested generics are now supported. The contents of a generic statement are no longer highlighted as a `function`, but as a `class-name` which is more fitting. 3. Packages will now be highlighted as `namespace`. 4. E.g. `foo::bar`, `bar` will be highlighted as a function. 5. ~Support for `var`.~ #1549 6. `null` is now a keyword. As it should be. --- components/prism-java.js | 75 +++++++++++++------- components/prism-java.min.js | 2 +- tests/languages/java/function_featrue.test | 32 +++++++++ tests/languages/java/generics_feature.test | 28 ++++---- tests/languages/java/issue1351.test | 14 ++-- tests/languages/java/keyword_feature.test | 32 +++++---- tests/languages/java/number_feature.test | 53 +++++++++++--- tests/languages/java/package_feature.test | 80 ++++++++++++++++++++++ 8 files changed, 246 insertions(+), 70 deletions(-) create mode 100644 tests/languages/java/function_featrue.test create mode 100644 tests/languages/java/package_feature.test diff --git a/components/prism-java.js b/components/prism-java.js index 229333bef4..fb138409bb 100644 --- a/components/prism-java.js +++ b/components/prism-java.js @@ -1,27 +1,54 @@ -Prism.languages.java = Prism.languages.extend('clike', { - 'keyword': /\b(?:var|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/, - 'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp-]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?[df]?/i, - 'operator': { - pattern: /(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m, - lookbehind: true - } -}); +(function (Prism) { -Prism.languages.insertBefore('java','function', { - 'annotation': { - alias: 'punctuation', - pattern: /(^|[^.])@\w+/, - lookbehind: true - } -}); + var keywords = /\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while|var|null)\b/; -Prism.languages.insertBefore('java', 'class-name', { - 'generics': { - pattern: /<\s*\w+(?:\.\w+)?(?:\s*,\s*\w+(?:\.\w+)?)*>/i, - alias: 'function', - inside: { - keyword: Prism.languages.java.keyword, - punctuation: /[<>(),.:]/ + // based on the java naming conventions + var className = /\b[A-Z](?:\w*[a-z]\w*)?\b/; + + Prism.languages.java = Prism.languages.extend('clike', { + 'class-name': [ + className, + + // variables and parameters + // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods) + /\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/ + ], + 'keyword': keywords, + 'function': [ + Prism.languages.clike.function, + { + pattern: /(\:\:)[a-z_]\w*/, + lookbehind: true + } + ], + 'number': /\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i, + 'operator': { + pattern: /(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m, + lookbehind: true + } + }); + + Prism.languages.insertBefore('java', 'class-name', { + 'annotation': { + alias: 'punctuation', + pattern: /(^|[^.])@\w+/, + lookbehind: true + }, + 'namespace': { + pattern: /\b(package\s+|import\s+(?:static\s+)?)[a-z]\w*(\.[a-z]\w*)+/, + lookbehind: true, + inside: { + 'punctuation': /\./, + } + }, + 'generics': { + pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, + inside: { + 'class-name': className, + 'keyword': keywords, + 'punctuation': /[<>(),.:]/, + 'operator': /[?&|]/ + } } - } -}); + }); +}(Prism)); diff --git a/components/prism-java.min.js b/components/prism-java.min.js index ea612551d1..c71824743d 100644 --- a/components/prism-java.min.js +++ b/components/prism-java.min.js @@ -1 +1 @@ -Prism.languages.java=Prism.languages.extend("clike",{keyword:/\b(?:var|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp-]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?[df]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*\/%&|^!=<>]=?)/m,lookbehind:!0}}),Prism.languages.insertBefore("java","function",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0}}),Prism.languages.insertBefore("java","class-name",{generics:{pattern:/<\s*\w+(?:\.\w+)?(?:\s*,\s*\w+(?:\.\w+)?)*>/i,alias:"function",inside:{keyword:Prism.languages.java.keyword,punctuation:/[<>(),.:]/}}}); \ No newline at end of file +!function(a){var e=/\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while|var|null)\b/,t=/\b[A-Z](?:\w*[a-z]\w*)?\b/;a.languages.java=a.languages.extend("clike",{"class-name":[t,/\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/],keyword:e,"function":[a.languages.clike.function,{pattern:/(\:\:)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*\/%&|^!=<>]=?)/m,lookbehind:!0}}),a.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:/\b(package\s+|import\s+(?:static\s+)?)[a-z]\w*(\.[a-z]\w*)+/,lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":t,keyword:e,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); \ No newline at end of file diff --git a/tests/languages/java/function_featrue.test b/tests/languages/java/function_featrue.test new file mode 100644 index 0000000000..2ca6169f8e --- /dev/null +++ b/tests/languages/java/function_featrue.test @@ -0,0 +1,32 @@ +void foo(int a) {} +foo(0); +Bar::foo; + +---------------------------------------------------- + +[ + ["keyword", "void"], + ["function", "foo"], + ["punctuation", "("], + ["keyword", "int"], + " a", + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["function", "foo"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["class-name", "Bar"], + ["operator", ":"], + ["operator", ":"], + ["function", "foo"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for functions. diff --git a/tests/languages/java/generics_feature.test b/tests/languages/java/generics_feature.test index 66bfef58bb..d1d5e5363a 100644 --- a/tests/languages/java/generics_feature.test +++ b/tests/languages/java/generics_feature.test @@ -7,49 +7,51 @@ Duo dual = new Duo(12.2585, 'C'); [ ["keyword", "public"], ["keyword", "class"], - ["class-name", ["Solo"]], + ["class-name", "Solo"], ["generics", [ ["punctuation", "<"], - "T", + ["class-name", "T"], ["punctuation", ">"] ]], ["punctuation", "{"], ["punctuation", "}"], - "\r\nSolo", + + ["class-name", "Solo"], ["generics", [ ["punctuation", "<"], - "Integer", + ["class-name", "Integer"], ["punctuation", ">"] ]], " val ", ["operator", "="], ["keyword", "new"], - ["class-name", ["Solo"]], + ["class-name", "Solo"], ["generics", [ ["punctuation", "<"], - "Integer", + ["class-name", "Integer"], ["punctuation", ">"] ]], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], - "\r\nDuo", + + ["class-name", "Duo"], ["generics", [ ["punctuation", "<"], - "Double", + ["class-name", "Double"], ["punctuation", ","], - " Character", + ["class-name", "Character"], ["punctuation", ">"] ]], " dual ", ["operator", "="], ["keyword", "new"], - ["class-name", ["Duo"]], + ["class-name", "Duo"], ["generics", [ ["punctuation", "<"], - "Double", + ["class-name", "Double"], ["punctuation", ","], - " Character", + ["class-name", "Character"], ["punctuation", ">"] ]], ["punctuation", "("], @@ -62,4 +64,4 @@ Duo dual = new Duo(12.2585, 'C'); ---------------------------------------------------- -Checks for generics. \ No newline at end of file +Checks for generics. diff --git a/tests/languages/java/issue1351.test b/tests/languages/java/issue1351.test index 0162eec6c4..3034e3e857 100644 --- a/tests/languages/java/issue1351.test +++ b/tests/languages/java/issue1351.test @@ -5,18 +5,18 @@ public class AllChangesIndexer extends SiteIndexer"] ]], ["punctuation", "{"] @@ -24,4 +24,4 @@ public class AllChangesIndexer extends SiteIndexer