java.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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. ];
  103. const BUILT_INS = [
  104. 'super',
  105. 'this'
  106. ];
  107. const LITERALS = [
  108. 'false',
  109. 'true',
  110. 'null'
  111. ];
  112. const TYPES = [
  113. 'char',
  114. 'boolean',
  115. 'long',
  116. 'float',
  117. 'int',
  118. 'byte',
  119. 'short',
  120. 'double'
  121. ];
  122. const KEYWORDS = {
  123. keyword: MAIN_KEYWORDS,
  124. literal: LITERALS,
  125. type: TYPES,
  126. built_in: BUILT_INS
  127. };
  128. const ANNOTATION = {
  129. className: 'meta',
  130. begin: '@' + JAVA_IDENT_RE,
  131. contains: [
  132. {
  133. begin: /\(/,
  134. end: /\)/,
  135. contains: [ "self" ] // allow nested () inside our annotation
  136. }
  137. ]
  138. };
  139. const PARAMS = {
  140. className: 'params',
  141. begin: /\(/,
  142. end: /\)/,
  143. keywords: KEYWORDS,
  144. relevance: 0,
  145. contains: [ hljs.C_BLOCK_COMMENT_MODE ],
  146. endsParent: true
  147. };
  148. return {
  149. name: 'Java',
  150. aliases: [ 'jsp' ],
  151. keywords: KEYWORDS,
  152. illegal: /<\/|#/,
  153. contains: [
  154. hljs.COMMENT(
  155. '/\\*\\*',
  156. '\\*/',
  157. {
  158. relevance: 0,
  159. contains: [
  160. {
  161. // eat up @'s in emails to prevent them to be recognized as doctags
  162. begin: /\w+@/,
  163. relevance: 0
  164. },
  165. {
  166. className: 'doctag',
  167. begin: '@[A-Za-z]+'
  168. }
  169. ]
  170. }
  171. ),
  172. // relevance boost
  173. {
  174. begin: /import java\.[a-z]+\./,
  175. keywords: "import",
  176. relevance: 2
  177. },
  178. hljs.C_LINE_COMMENT_MODE,
  179. hljs.C_BLOCK_COMMENT_MODE,
  180. {
  181. begin: /"""/,
  182. end: /"""/,
  183. className: "string",
  184. contains: [ hljs.BACKSLASH_ESCAPE ]
  185. },
  186. hljs.APOS_STRING_MODE,
  187. hljs.QUOTE_STRING_MODE,
  188. {
  189. match: [
  190. /\b(?:class|interface|enum|extends|implements|new)/,
  191. /\s+/,
  192. JAVA_IDENT_RE
  193. ],
  194. className: {
  195. 1: "keyword",
  196. 3: "title.class"
  197. }
  198. },
  199. {
  200. // Exceptions for hyphenated keywords
  201. match: /non-sealed/,
  202. scope: "keyword"
  203. },
  204. {
  205. begin: [
  206. regex.concat(/(?!else)/, JAVA_IDENT_RE),
  207. /\s+/,
  208. JAVA_IDENT_RE,
  209. /\s+/,
  210. /=(?!=)/
  211. ],
  212. className: {
  213. 1: "type",
  214. 3: "variable",
  215. 5: "operator"
  216. }
  217. },
  218. {
  219. begin: [
  220. /record/,
  221. /\s+/,
  222. JAVA_IDENT_RE
  223. ],
  224. className: {
  225. 1: "keyword",
  226. 3: "title.class"
  227. },
  228. contains: [
  229. PARAMS,
  230. hljs.C_LINE_COMMENT_MODE,
  231. hljs.C_BLOCK_COMMENT_MODE
  232. ]
  233. },
  234. {
  235. // Expression keywords prevent 'keyword Name(...)' from being
  236. // recognized as a function definition
  237. beginKeywords: 'new throw return else',
  238. relevance: 0
  239. },
  240. {
  241. begin: [
  242. '(?:' + GENERIC_IDENT_RE + '\\s+)',
  243. hljs.UNDERSCORE_IDENT_RE,
  244. /\s*(?=\()/
  245. ],
  246. className: { 2: "title.function" },
  247. keywords: KEYWORDS,
  248. contains: [
  249. {
  250. className: 'params',
  251. begin: /\(/,
  252. end: /\)/,
  253. keywords: KEYWORDS,
  254. relevance: 0,
  255. contains: [
  256. ANNOTATION,
  257. hljs.APOS_STRING_MODE,
  258. hljs.QUOTE_STRING_MODE,
  259. NUMERIC,
  260. hljs.C_BLOCK_COMMENT_MODE
  261. ]
  262. },
  263. hljs.C_LINE_COMMENT_MODE,
  264. hljs.C_BLOCK_COMMENT_MODE
  265. ]
  266. },
  267. NUMERIC,
  268. ANNOTATION
  269. ]
  270. };
  271. }
  272. export { java as default };