java.js 6.1 KB

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