UNPKG

6.17 kBJavaScriptView Raw
1// https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10
2var decimalDigits = '[0-9](_*[0-9])*';
3var frac = `\\.(${decimalDigits})`;
4var hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*';
5var NUMERIC = {
6 className: 'number',
7 variants: [
8 // DecimalFloatingPointLiteral
9 // including ExponentPart
10 { begin: `(\\b(${decimalDigits})((${frac})|\\.)?|(${frac}))` +
11 `[eE][+-]?(${decimalDigits})[fFdD]?\\b` },
12 // excluding ExponentPart
13 { begin: `\\b(${decimalDigits})((${frac})[fFdD]?\\b|\\.([fFdD]\\b)?)` },
14 { begin: `(${frac})[fFdD]?\\b` },
15 { begin: `\\b(${decimalDigits})[fFdD]\\b` },
16
17 // HexadecimalFloatingPointLiteral
18 { begin: `\\b0[xX]((${hexDigits})\\.?|(${hexDigits})?\\.(${hexDigits}))` +
19 `[pP][+-]?(${decimalDigits})[fFdD]?\\b` },
20
21 // DecimalIntegerLiteral
22 { begin: '\\b(0|[1-9](_*[0-9])*)[lL]?\\b' },
23
24 // HexIntegerLiteral
25 { begin: `\\b0[xX](${hexDigits})[lL]?\\b` },
26
27 // OctalIntegerLiteral
28 { begin: '\\b0(_*[0-7])*[lL]?\\b' },
29
30 // BinaryIntegerLiteral
31 { begin: '\\b0[bB][01](_*[01])*[lL]?\\b' },
32 ],
33 relevance: 0
34};
35
36/*
37Language: Java
38Author: Vsevolod Solovyov <vsevolod.solovyov@gmail.com>
39Category: common, enterprise
40Website: https://www.java.com/
41*/
42
43/**
44 * Allows recursive regex expressions to a given depth
45 *
46 * ie: recurRegex("(abc~~~)", /~~~/g, 2) becomes:
47 * (abc(abc(abc)))
48 *
49 * @param {string} re
50 * @param {RegExp} substitution (should be a g mode regex)
51 * @param {number} depth
52 * @returns {string}``
53 */
54function recurRegex(re, substitution, depth) {
55 if (depth === -1) return "";
56
57 return re.replace(substitution, _ => {
58 return recurRegex(re, substitution, depth - 1);
59 });
60}
61
62/** @type LanguageFn */
63function java(hljs) {
64 const regex = hljs.regex;
65 const JAVA_IDENT_RE = '[\u00C0-\u02B8a-zA-Z_$][\u00C0-\u02B8a-zA-Z_$0-9]*';
66 const GENERIC_IDENT_RE = JAVA_IDENT_RE
67 + recurRegex('(?:<' + JAVA_IDENT_RE + '~~~(?:\\s*,\\s*' + JAVA_IDENT_RE + '~~~)*>)?', /~~~/g, 2);
68 const MAIN_KEYWORDS = [
69 'synchronized',
70 'abstract',
71 'private',
72 'var',
73 'static',
74 'if',
75 'const ',
76 'for',
77 'while',
78 'strictfp',
79 'finally',
80 'protected',
81 'import',
82 'native',
83 'final',
84 'void',
85 'enum',
86 'else',
87 'break',
88 'transient',
89 'catch',
90 'instanceof',
91 'volatile',
92 'case',
93 'assert',
94 'package',
95 'default',
96 'public',
97 'try',
98 'switch',
99 'continue',
100 'throws',
101 'protected',
102 'public',
103 'private',
104 'module',
105 'requires',
106 'exports',
107 'do',
108 'sealed'
109 ];
110
111 const BUILT_INS = [
112 'super',
113 'this'
114 ];
115
116 const LITERALS = [
117 'false',
118 'true',
119 'null'
120 ];
121
122 const TYPES = [
123 'char',
124 'boolean',
125 'long',
126 'float',
127 'int',
128 'byte',
129 'short',
130 'double'
131 ];
132
133 const KEYWORDS = {
134 keyword: MAIN_KEYWORDS,
135 literal: LITERALS,
136 type: TYPES,
137 built_in: BUILT_INS
138 };
139
140 const ANNOTATION = {
141 className: 'meta',
142 begin: '@' + JAVA_IDENT_RE,
143 contains: [
144 {
145 begin: /\(/,
146 end: /\)/,
147 contains: [ "self" ] // allow nested () inside our annotation
148 }
149 ]
150 };
151 const PARAMS = {
152 className: 'params',
153 begin: /\(/,
154 end: /\)/,
155 keywords: KEYWORDS,
156 relevance: 0,
157 contains: [ hljs.C_BLOCK_COMMENT_MODE ],
158 endsParent: true
159 };
160
161 return {
162 name: 'Java',
163 aliases: [ 'jsp' ],
164 keywords: KEYWORDS,
165 illegal: /<\/|#/,
166 contains: [
167 hljs.COMMENT(
168 '/\\*\\*',
169 '\\*/',
170 {
171 relevance: 0,
172 contains: [
173 {
174 // eat up @'s in emails to prevent them to be recognized as doctags
175 begin: /\w+@/,
176 relevance: 0
177 },
178 {
179 className: 'doctag',
180 begin: '@[A-Za-z]+'
181 }
182 ]
183 }
184 ),
185 // relevance boost
186 {
187 begin: /import java\.[a-z]+\./,
188 keywords: "import",
189 relevance: 2
190 },
191 hljs.C_LINE_COMMENT_MODE,
192 hljs.C_BLOCK_COMMENT_MODE,
193 {
194 begin: /"""/,
195 end: /"""/,
196 className: "string",
197 contains: [ hljs.BACKSLASH_ESCAPE ]
198 },
199 hljs.APOS_STRING_MODE,
200 hljs.QUOTE_STRING_MODE,
201 {
202 match: [
203 /\b(?:class|interface|enum|extends|implements|new)/,
204 /\s+/,
205 JAVA_IDENT_RE
206 ],
207 className: {
208 1: "keyword",
209 3: "title.class"
210 }
211 },
212 {
213 // Exceptions for hyphenated keywords
214 match: /non-sealed/,
215 scope: "keyword"
216 },
217 {
218 begin: [
219 regex.concat(/(?!else)/, JAVA_IDENT_RE),
220 /\s+/,
221 JAVA_IDENT_RE,
222 /\s+/,
223 /=/
224 ],
225 className: {
226 1: "type",
227 3: "variable",
228 5: "operator"
229 }
230 },
231 {
232 begin: [
233 /record/,
234 /\s+/,
235 JAVA_IDENT_RE
236 ],
237 className: {
238 1: "keyword",
239 3: "title.class"
240 },
241 contains: [
242 PARAMS,
243 hljs.C_LINE_COMMENT_MODE,
244 hljs.C_BLOCK_COMMENT_MODE
245 ]
246 },
247 {
248 // Expression keywords prevent 'keyword Name(...)' from being
249 // recognized as a function definition
250 beginKeywords: 'new throw return else',
251 relevance: 0
252 },
253 {
254 begin: [
255 '(?:' + GENERIC_IDENT_RE + '\\s+)',
256 hljs.UNDERSCORE_IDENT_RE,
257 /\s*(?=\()/
258 ],
259 className: { 2: "title.function" },
260 keywords: KEYWORDS,
261 contains: [
262 {
263 className: 'params',
264 begin: /\(/,
265 end: /\)/,
266 keywords: KEYWORDS,
267 relevance: 0,
268 contains: [
269 ANNOTATION,
270 hljs.APOS_STRING_MODE,
271 hljs.QUOTE_STRING_MODE,
272 NUMERIC,
273 hljs.C_BLOCK_COMMENT_MODE
274 ]
275 },
276 hljs.C_LINE_COMMENT_MODE,
277 hljs.C_BLOCK_COMMENT_MODE
278 ]
279 },
280 NUMERIC,
281 ANNOTATION
282 ]
283 };
284}
285
286module.exports = java;