swift.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /**
  2. * @param {string} value
  3. * @returns {RegExp}
  4. * */
  5. /**
  6. * @param {RegExp | string } re
  7. * @returns {string}
  8. */
  9. function source(re) {
  10. if (!re) return null;
  11. if (typeof re === "string") return re;
  12. return re.source;
  13. }
  14. /**
  15. * @param {RegExp | string } re
  16. * @returns {string}
  17. */
  18. function lookahead(re) {
  19. return concat('(?=', re, ')');
  20. }
  21. /**
  22. * @param {...(RegExp | string) } args
  23. * @returns {string}
  24. */
  25. function concat(...args) {
  26. const joined = args.map((x) => source(x)).join("");
  27. return joined;
  28. }
  29. /**
  30. * Any of the passed expresssions may match
  31. *
  32. * Creates a huge this | this | that | that match
  33. * @param {(RegExp | string)[] } args
  34. * @returns {string}
  35. */
  36. function either(...args) {
  37. const joined = '(' + args.map((x) => source(x)).join("|") + ")";
  38. return joined;
  39. }
  40. const keywordWrapper = keyword => concat(
  41. /\b/,
  42. keyword,
  43. /\w$/.test(keyword) ? /\b/ : /\B/
  44. );
  45. // Keywords that require a leading dot.
  46. const dotKeywords = [
  47. 'Protocol', // contextual
  48. 'Type' // contextual
  49. ].map(keywordWrapper);
  50. // Keywords that may have a leading dot.
  51. const optionalDotKeywords = [
  52. 'init',
  53. 'self'
  54. ].map(keywordWrapper);
  55. // should register as keyword, not type
  56. const keywordTypes = [
  57. 'Any',
  58. 'Self'
  59. ];
  60. // Regular keywords and literals.
  61. const keywords = [
  62. // strings below will be fed into the regular `keywords` engine while regex
  63. // will result in additional modes being created to scan for those keywords to
  64. // avoid conflicts with other rules
  65. 'associatedtype',
  66. /as\?/, // operator
  67. /as!/, // operator
  68. 'as', // operator
  69. 'break',
  70. 'case',
  71. 'catch',
  72. 'class',
  73. 'continue',
  74. 'convenience', // contextual
  75. 'default',
  76. 'defer',
  77. 'deinit',
  78. 'didSet', // contextual
  79. 'do',
  80. 'dynamic', // contextual
  81. 'else',
  82. 'enum',
  83. 'extension',
  84. 'fallthrough',
  85. 'fileprivate(set)',
  86. 'fileprivate',
  87. 'final', // contextual
  88. 'for',
  89. 'func',
  90. 'get', // contextual
  91. 'guard',
  92. 'if',
  93. 'import',
  94. 'indirect', // contextual
  95. 'infix', // contextual
  96. /init\?/,
  97. /init!/,
  98. 'inout',
  99. 'internal(set)',
  100. 'internal',
  101. 'in',
  102. 'is', // operator
  103. 'lazy', // contextual
  104. 'let',
  105. 'mutating', // contextual
  106. 'nonmutating', // contextual
  107. 'open(set)', // contextual
  108. 'open', // contextual
  109. 'operator',
  110. 'optional', // contextual
  111. 'override', // contextual
  112. 'postfix', // contextual
  113. 'precedencegroup',
  114. 'prefix', // contextual
  115. 'private(set)',
  116. 'private',
  117. 'protocol',
  118. 'public(set)',
  119. 'public',
  120. 'repeat',
  121. 'required', // contextual
  122. 'rethrows',
  123. 'return',
  124. 'set', // contextual
  125. 'some', // contextual
  126. 'static',
  127. 'struct',
  128. 'subscript',
  129. 'super',
  130. 'switch',
  131. 'throws',
  132. 'throw',
  133. /try\?/, // operator
  134. /try!/, // operator
  135. 'try', // operator
  136. 'typealias',
  137. 'unowned(safe)', // contextual
  138. 'unowned(unsafe)', // contextual
  139. 'unowned', // contextual
  140. 'var',
  141. 'weak', // contextual
  142. 'where',
  143. 'while',
  144. 'willSet' // contextual
  145. ];
  146. // NOTE: Contextual keywords are reserved only in specific contexts.
  147. // Ideally, these should be matched using modes to avoid false positives.
  148. // TODO: Create a PRECEDENCE_GROUP mode to match the remaining contextual keywords:
  149. // assignment associativity higherThan left lowerThan none right
  150. // These aren't included in the list because they result in mostly false positives.
  151. // Literals.
  152. const literals = [
  153. 'false',
  154. 'nil',
  155. 'true'
  156. ];
  157. // Keywords that start with a number sign (#).
  158. // #available is handled separately.
  159. const numberSignKeywords = [
  160. '#colorLiteral',
  161. '#column',
  162. '#dsohandle',
  163. '#else',
  164. '#elseif',
  165. '#endif',
  166. '#error',
  167. '#file',
  168. '#fileID',
  169. '#fileLiteral',
  170. '#filePath',
  171. '#function',
  172. '#if',
  173. '#imageLiteral',
  174. '#keyPath',
  175. '#line',
  176. '#selector',
  177. '#sourceLocation',
  178. '#warn_unqualified_access',
  179. '#warning'
  180. ];
  181. // Global functions in the Standard Library.
  182. const builtIns = [
  183. 'abs',
  184. 'all',
  185. 'any',
  186. 'assert',
  187. 'assertionFailure',
  188. 'debugPrint',
  189. 'dump',
  190. 'fatalError',
  191. 'getVaList',
  192. 'isKnownUniquelyReferenced',
  193. 'max',
  194. 'min',
  195. 'numericCast',
  196. 'pointwiseMax',
  197. 'pointwiseMin',
  198. 'precondition',
  199. 'preconditionFailure',
  200. 'print',
  201. 'readLine',
  202. 'repeatElement',
  203. 'sequence',
  204. 'stride',
  205. 'swap',
  206. 'swift_unboxFromSwiftValueWithType',
  207. 'transcode',
  208. 'type',
  209. 'unsafeBitCast',
  210. 'unsafeDowncast',
  211. 'withExtendedLifetime',
  212. 'withUnsafeMutablePointer',
  213. 'withUnsafePointer',
  214. 'withVaList',
  215. 'withoutActuallyEscaping',
  216. 'zip'
  217. ];
  218. // Valid first characters for operators.
  219. const operatorHead = either(
  220. /[/=\-+!*%<>&|^~?]/,
  221. /[\u00A1-\u00A7]/,
  222. /[\u00A9\u00AB]/,
  223. /[\u00AC\u00AE]/,
  224. /[\u00B0\u00B1]/,
  225. /[\u00B6\u00BB\u00BF\u00D7\u00F7]/,
  226. /[\u2016-\u2017]/,
  227. /[\u2020-\u2027]/,
  228. /[\u2030-\u203E]/,
  229. /[\u2041-\u2053]/,
  230. /[\u2055-\u205E]/,
  231. /[\u2190-\u23FF]/,
  232. /[\u2500-\u2775]/,
  233. /[\u2794-\u2BFF]/,
  234. /[\u2E00-\u2E7F]/,
  235. /[\u3001-\u3003]/,
  236. /[\u3008-\u3020]/,
  237. /[\u3030]/
  238. );
  239. // Valid characters for operators.
  240. const operatorCharacter = either(
  241. operatorHead,
  242. /[\u0300-\u036F]/,
  243. /[\u1DC0-\u1DFF]/,
  244. /[\u20D0-\u20FF]/,
  245. /[\uFE00-\uFE0F]/,
  246. /[\uFE20-\uFE2F]/
  247. // TODO: The following characters are also allowed, but the regex isn't supported yet.
  248. // /[\u{E0100}-\u{E01EF}]/u
  249. );
  250. // Valid operator.
  251. const operator = concat(operatorHead, operatorCharacter, '*');
  252. // Valid first characters for identifiers.
  253. const identifierHead = either(
  254. /[a-zA-Z_]/,
  255. /[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,
  256. /[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,
  257. /[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,
  258. /[\u1E00-\u1FFF]/,
  259. /[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,
  260. /[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,
  261. /[\u2C00-\u2DFF\u2E80-\u2FFF]/,
  262. /[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,
  263. /[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,
  264. /[\uFE47-\uFFFD]/
  265. // The following characters are also allowed, but the regexes aren't supported yet.
  266. // /[\u{10000}-\u{1FFFD}\u{20000-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}]/u,
  267. // /[\u{50000}-\u{5FFFD}\u{60000-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}]/u,
  268. // /[\u{90000}-\u{9FFFD}\u{A0000-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}]/u,
  269. // /[\u{D0000}-\u{DFFFD}\u{E0000-\u{EFFFD}]/u
  270. );
  271. // Valid characters for identifiers.
  272. const identifierCharacter = either(
  273. identifierHead,
  274. /\d/,
  275. /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/
  276. );
  277. // Valid identifier.
  278. const identifier = concat(identifierHead, identifierCharacter, '*');
  279. // Valid type identifier.
  280. const typeIdentifier = concat(/[A-Z]/, identifierCharacter, '*');
  281. // Built-in attributes, which are highlighted as keywords.
  282. // @available is handled separately.
  283. const keywordAttributes = [
  284. 'autoclosure',
  285. concat(/convention\(/, either('swift', 'block', 'c'), /\)/),
  286. 'discardableResult',
  287. 'dynamicCallable',
  288. 'dynamicMemberLookup',
  289. 'escaping',
  290. 'frozen',
  291. 'GKInspectable',
  292. 'IBAction',
  293. 'IBDesignable',
  294. 'IBInspectable',
  295. 'IBOutlet',
  296. 'IBSegueAction',
  297. 'inlinable',
  298. 'main',
  299. 'nonobjc',
  300. 'NSApplicationMain',
  301. 'NSCopying',
  302. 'NSManaged',
  303. concat(/objc\(/, identifier, /\)/),
  304. 'objc',
  305. 'objcMembers',
  306. 'propertyWrapper',
  307. 'requires_stored_property_inits',
  308. 'testable',
  309. 'UIApplicationMain',
  310. 'unknown',
  311. 'usableFromInline'
  312. ];
  313. // Contextual keywords used in @available and #available.
  314. const availabilityKeywords = [
  315. 'iOS',
  316. 'iOSApplicationExtension',
  317. 'macOS',
  318. 'macOSApplicationExtension',
  319. 'macCatalyst',
  320. 'macCatalystApplicationExtension',
  321. 'watchOS',
  322. 'watchOSApplicationExtension',
  323. 'tvOS',
  324. 'tvOSApplicationExtension',
  325. 'swift'
  326. ];
  327. /*
  328. Language: Swift
  329. Description: Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
  330. Author: Steven Van Impe <steven.vanimpe@icloud.com>
  331. Contributors: Chris Eidhof <chris@eidhof.nl>, Nate Cook <natecook@gmail.com>, Alexander Lichter <manniL@gmx.net>, Richard Gibson <gibson042@github>
  332. Website: https://swift.org
  333. Category: common, system
  334. */
  335. /** @type LanguageFn */
  336. function swift(hljs) {
  337. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID411
  338. const BLOCK_COMMENT = hljs.COMMENT(
  339. '/\\*',
  340. '\\*/',
  341. {
  342. contains: [ 'self' ]
  343. }
  344. );
  345. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID413
  346. // https://docs.swift.org/swift-book/ReferenceManual/zzSummaryOfTheGrammar.html
  347. const DOT_KEYWORD = {
  348. className: 'keyword',
  349. begin: concat(/\./, lookahead(either(...dotKeywords, ...optionalDotKeywords))),
  350. end: either(...dotKeywords, ...optionalDotKeywords),
  351. excludeBegin: true
  352. };
  353. const KEYWORD_GUARD = {
  354. // Consume .keyword to prevent highlighting properties and methods as keywords.
  355. begin: concat(/\./, either(...keywords)),
  356. relevance: 0
  357. };
  358. const PLAIN_KEYWORDS = keywords
  359. .filter(kw => typeof kw === 'string')
  360. .concat([ "_|0" ]); // seems common, so 0 relevance
  361. const REGEX_KEYWORDS = keywords
  362. .filter(kw => typeof kw !== 'string') // find regex
  363. .concat(keywordTypes)
  364. .map(keywordWrapper);
  365. const KEYWORD = {
  366. variants: [
  367. {
  368. className: 'keyword',
  369. begin: either(...REGEX_KEYWORDS, ...optionalDotKeywords)
  370. }
  371. ]
  372. };
  373. // find all the regular keywords
  374. const KEYWORDS = {
  375. $pattern: either(
  376. /\b\w+(\(\w+\))?/, // kw or kw(arg)
  377. /#\w+/ // number keywords
  378. ),
  379. keyword: PLAIN_KEYWORDS
  380. .concat(numberSignKeywords)
  381. .join(" "),
  382. literal: literals.join(" ")
  383. };
  384. const KEYWORD_MODES = [
  385. DOT_KEYWORD,
  386. KEYWORD_GUARD,
  387. KEYWORD
  388. ];
  389. // https://github.com/apple/swift/tree/main/stdlib/public/core
  390. const BUILT_IN_GUARD = {
  391. // Consume .built_in to prevent highlighting properties and methods.
  392. begin: concat(/\./, either(...builtIns)),
  393. relevance: 0
  394. };
  395. const BUILT_IN = {
  396. className: 'built_in',
  397. begin: concat(/\b/, either(...builtIns), /(?=\()/)
  398. };
  399. const BUILT_INS = [
  400. BUILT_IN_GUARD,
  401. BUILT_IN
  402. ];
  403. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
  404. const OPERATOR_GUARD = {
  405. // Prevent -> from being highlighting as an operator.
  406. begin: /->/,
  407. relevance: 0
  408. };
  409. const OPERATOR = {
  410. className: 'operator',
  411. relevance: 0,
  412. variants: [
  413. {
  414. begin: operator
  415. },
  416. {
  417. // dot-operator: only operators that start with a dot are allowed to use dots as
  418. // characters (..., ...<, .*, etc). So there rule here is: a dot followed by one or more
  419. // characters that may also include dots.
  420. begin: `\\.(\\.|${operatorCharacter})+`
  421. }
  422. ]
  423. };
  424. const OPERATORS = [
  425. OPERATOR_GUARD,
  426. OPERATOR
  427. ];
  428. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_numeric-literal
  429. // TODO: Update for leading `-` after lookbehind is supported everywhere
  430. const decimalDigits = '([0-9]_*)+';
  431. const hexDigits = '([0-9a-fA-F]_*)+';
  432. const NUMBER = {
  433. className: 'number',
  434. relevance: 0,
  435. variants: [
  436. // decimal floating-point-literal (subsumes decimal-literal)
  437. {
  438. begin: `\\b(${decimalDigits})(\\.(${decimalDigits}))?` + `([eE][+-]?(${decimalDigits}))?\\b`
  439. },
  440. // hexadecimal floating-point-literal (subsumes hexadecimal-literal)
  441. {
  442. begin: `\\b0x(${hexDigits})(\\.(${hexDigits}))?` + `([pP][+-]?(${decimalDigits}))?\\b`
  443. },
  444. // octal-literal
  445. {
  446. begin: /\b0o([0-7]_*)+\b/
  447. },
  448. // binary-literal
  449. {
  450. begin: /\b0b([01]_*)+\b/
  451. }
  452. ]
  453. };
  454. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_string-literal
  455. const ESCAPED_CHARACTER = (rawDelimiter = "") => ({
  456. className: 'subst',
  457. variants: [
  458. {
  459. begin: concat(/\\/, rawDelimiter, /[0\\tnr"']/)
  460. },
  461. {
  462. begin: concat(/\\/, rawDelimiter, /u\{[0-9a-fA-F]{1,8}\}/)
  463. }
  464. ]
  465. });
  466. const ESCAPED_NEWLINE = (rawDelimiter = "") => ({
  467. className: 'subst',
  468. begin: concat(/\\/, rawDelimiter, /[\t ]*(?:[\r\n]|\r\n)/)
  469. });
  470. const INTERPOLATION = (rawDelimiter = "") => ({
  471. className: 'subst',
  472. label: "interpol",
  473. begin: concat(/\\/, rawDelimiter, /\(/),
  474. end: /\)/
  475. });
  476. const MULTILINE_STRING = (rawDelimiter = "") => ({
  477. begin: concat(rawDelimiter, /"""/),
  478. end: concat(/"""/, rawDelimiter),
  479. contains: [
  480. ESCAPED_CHARACTER(rawDelimiter),
  481. ESCAPED_NEWLINE(rawDelimiter),
  482. INTERPOLATION(rawDelimiter)
  483. ]
  484. });
  485. const SINGLE_LINE_STRING = (rawDelimiter = "") => ({
  486. begin: concat(rawDelimiter, /"/),
  487. end: concat(/"/, rawDelimiter),
  488. contains: [
  489. ESCAPED_CHARACTER(rawDelimiter),
  490. INTERPOLATION(rawDelimiter)
  491. ]
  492. });
  493. const STRING = {
  494. className: 'string',
  495. variants: [
  496. MULTILINE_STRING(),
  497. MULTILINE_STRING("#"),
  498. MULTILINE_STRING("##"),
  499. MULTILINE_STRING("###"),
  500. SINGLE_LINE_STRING(),
  501. SINGLE_LINE_STRING("#"),
  502. SINGLE_LINE_STRING("##"),
  503. SINGLE_LINE_STRING("###")
  504. ]
  505. };
  506. // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID412
  507. const QUOTED_IDENTIFIER = {
  508. begin: concat(/`/, identifier, /`/)
  509. };
  510. const IMPLICIT_PARAMETER = {
  511. className: 'variable',
  512. begin: /\$\d+/
  513. };
  514. const PROPERTY_WRAPPER_PROJECTION = {
  515. className: 'variable',
  516. begin: `\\$${identifierCharacter}+`
  517. };
  518. const IDENTIFIERS = [
  519. QUOTED_IDENTIFIER,
  520. IMPLICIT_PARAMETER,
  521. PROPERTY_WRAPPER_PROJECTION
  522. ];
  523. // https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
  524. const AVAILABLE_ATTRIBUTE = {
  525. begin: /(@|#)available\(/,
  526. end: /\)/,
  527. keywords: {
  528. $pattern: /[@#]?\w+/,
  529. keyword: availabilityKeywords
  530. .concat([
  531. "@available",
  532. "#available"
  533. ])
  534. .join(' ')
  535. },
  536. contains: [
  537. ...OPERATORS,
  538. NUMBER,
  539. STRING
  540. ]
  541. };
  542. const KEYWORD_ATTRIBUTE = {
  543. className: 'keyword',
  544. begin: concat(/@/, either(...keywordAttributes))
  545. };
  546. const USER_DEFINED_ATTRIBUTE = {
  547. className: 'meta',
  548. begin: concat(/@/, identifier)
  549. };
  550. const ATTRIBUTES = [
  551. AVAILABLE_ATTRIBUTE,
  552. KEYWORD_ATTRIBUTE,
  553. USER_DEFINED_ATTRIBUTE
  554. ];
  555. // https://docs.swift.org/swift-book/ReferenceManual/Types.html
  556. const TYPE = {
  557. begin: lookahead(/\b[A-Z]/),
  558. relevance: 0,
  559. contains: [
  560. { // Common Apple frameworks, for relevance boost
  561. className: 'type',
  562. begin: concat(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/, identifierCharacter, '+')
  563. },
  564. { // Type identifier
  565. className: 'type',
  566. begin: typeIdentifier,
  567. relevance: 0
  568. },
  569. { // Optional type
  570. begin: /[?!]+/,
  571. relevance: 0
  572. },
  573. { // Variadic parameter
  574. begin: /\.\.\./,
  575. relevance: 0
  576. },
  577. { // Protocol composition
  578. begin: concat(/\s+&\s+/, lookahead(typeIdentifier)),
  579. relevance: 0
  580. }
  581. ]
  582. };
  583. const GENERIC_ARGUMENTS = {
  584. begin: /</,
  585. end: />/,
  586. keywords: KEYWORDS,
  587. contains: [
  588. ...KEYWORD_MODES,
  589. ...ATTRIBUTES,
  590. OPERATOR_GUARD,
  591. TYPE
  592. ]
  593. };
  594. TYPE.contains.push(GENERIC_ARGUMENTS);
  595. // Add supported submodes to string interpolation.
  596. for (const variant of STRING.variants) {
  597. const interpolation = variant.contains.find(mode => mode.label === "interpol");
  598. // TODO: Interpolation can contain any expression, so there's room for improvement here.
  599. interpolation.keywords = KEYWORDS;
  600. const submodes = [
  601. ...KEYWORD_MODES,
  602. ...BUILT_INS,
  603. ...OPERATORS,
  604. NUMBER,
  605. STRING,
  606. ...IDENTIFIERS
  607. ];
  608. interpolation.contains = [
  609. ...submodes,
  610. {
  611. begin: /\(/,
  612. end: /\)/,
  613. contains: [
  614. 'self',
  615. ...submodes
  616. ]
  617. }
  618. ];
  619. }
  620. return {
  621. name: 'Swift',
  622. keywords: KEYWORDS,
  623. contains: [
  624. hljs.C_LINE_COMMENT_MODE,
  625. BLOCK_COMMENT,
  626. {
  627. className: 'function',
  628. beginKeywords: 'func',
  629. end: /\{/,
  630. excludeEnd: true,
  631. contains: [
  632. hljs.inherit(hljs.TITLE_MODE, {
  633. begin: /[A-Za-z$_][0-9A-Za-z$_]*/
  634. }),
  635. {
  636. begin: /</,
  637. end: />/
  638. },
  639. {
  640. className: 'params',
  641. begin: /\(/,
  642. end: /\)/,
  643. endsParent: true,
  644. keywords: KEYWORDS,
  645. contains: [
  646. 'self',
  647. ...KEYWORD_MODES,
  648. NUMBER,
  649. STRING,
  650. hljs.C_BLOCK_COMMENT_MODE,
  651. { // relevance booster
  652. begin: ':'
  653. }
  654. ],
  655. illegal: /["']/
  656. }
  657. ],
  658. illegal: /\[|%/
  659. },
  660. {
  661. className: 'class',
  662. beginKeywords: 'struct protocol class extension enum',
  663. end: '\\{',
  664. excludeEnd: true,
  665. keywords: KEYWORDS,
  666. contains: [
  667. hljs.inherit(hljs.TITLE_MODE, {
  668. begin: /[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/
  669. }),
  670. ...KEYWORD_MODES
  671. ]
  672. },
  673. {
  674. beginKeywords: 'import',
  675. end: /$/,
  676. contains: [
  677. hljs.C_LINE_COMMENT_MODE,
  678. BLOCK_COMMENT
  679. ],
  680. relevance: 0
  681. },
  682. ...KEYWORD_MODES,
  683. ...BUILT_INS,
  684. ...OPERATORS,
  685. NUMBER,
  686. STRING,
  687. ...IDENTIFIERS,
  688. ...ATTRIBUTES,
  689. TYPE
  690. ]
  691. };
  692. }
  693. module.exports = swift;