123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
- return re.source;
- }
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function lookahead(re) {
- return concat('(?=', re, ')');
- }
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
- /**
- * Any of the passed expresssions may match
- *
- * Creates a huge this | this | that | that match
- * @param {(RegExp | string)[] } args
- * @returns {string}
- */
- function either(...args) {
- const joined = '(' + args.map((x) => source(x)).join("|") + ")";
- return joined;
- }
- const keywordWrapper = keyword => concat(
- /\b/,
- keyword,
- /\w$/.test(keyword) ? /\b/ : /\B/
- );
- // Keywords that require a leading dot.
- const dotKeywords = [
- 'Protocol', // contextual
- 'Type' // contextual
- ].map(keywordWrapper);
- // Keywords that may have a leading dot.
- const optionalDotKeywords = [
- 'init',
- 'self'
- ].map(keywordWrapper);
- // should register as keyword, not type
- const keywordTypes = [
- 'Any',
- 'Self'
- ];
- // Regular keywords and literals.
- const keywords = [
- // strings below will be fed into the regular `keywords` engine while regex
- // will result in additional modes being created to scan for those keywords to
- // avoid conflicts with other rules
- 'associatedtype',
- 'async',
- 'await',
- /as\?/, // operator
- /as!/, // operator
- 'as', // operator
- 'break',
- 'case',
- 'catch',
- 'class',
- 'continue',
- 'convenience', // contextual
- 'default',
- 'defer',
- 'deinit',
- 'didSet', // contextual
- 'do',
- 'dynamic', // contextual
- 'else',
- 'enum',
- 'extension',
- 'fallthrough',
- /fileprivate\(set\)/,
- 'fileprivate',
- 'final', // contextual
- 'for',
- 'func',
- 'get', // contextual
- 'guard',
- 'if',
- 'import',
- 'indirect', // contextual
- 'infix', // contextual
- /init\?/,
- /init!/,
- 'inout',
- /internal\(set\)/,
- 'internal',
- 'in',
- 'is', // operator
- 'lazy', // contextual
- 'let',
- 'mutating', // contextual
- 'nonmutating', // contextual
- /open\(set\)/, // contextual
- 'open', // contextual
- 'operator',
- 'optional', // contextual
- 'override', // contextual
- 'postfix', // contextual
- 'precedencegroup',
- 'prefix', // contextual
- /private\(set\)/,
- 'private',
- 'protocol',
- /public\(set\)/,
- 'public',
- 'repeat',
- 'required', // contextual
- 'rethrows',
- 'return',
- 'set', // contextual
- 'some', // contextual
- 'static',
- 'struct',
- 'subscript',
- 'super',
- 'switch',
- 'throws',
- 'throw',
- /try\?/, // operator
- /try!/, // operator
- 'try', // operator
- 'typealias',
- /unowned\(safe\)/, // contextual
- /unowned\(unsafe\)/, // contextual
- 'unowned', // contextual
- 'var',
- 'weak', // contextual
- 'where',
- 'while',
- 'willSet' // contextual
- ];
- // NOTE: Contextual keywords are reserved only in specific contexts.
- // Ideally, these should be matched using modes to avoid false positives.
- // Literals.
- const literals = [
- 'false',
- 'nil',
- 'true'
- ];
- // Keywords used in precedence groups.
- const precedencegroupKeywords = [
- 'assignment',
- 'associativity',
- 'higherThan',
- 'left',
- 'lowerThan',
- 'none',
- 'right'
- ];
- // Keywords that start with a number sign (#).
- // #available is handled separately.
- const numberSignKeywords = [
- '#colorLiteral',
- '#column',
- '#dsohandle',
- '#else',
- '#elseif',
- '#endif',
- '#error',
- '#file',
- '#fileID',
- '#fileLiteral',
- '#filePath',
- '#function',
- '#if',
- '#imageLiteral',
- '#keyPath',
- '#line',
- '#selector',
- '#sourceLocation',
- '#warn_unqualified_access',
- '#warning'
- ];
- // Global functions in the Standard Library.
- const builtIns = [
- 'abs',
- 'all',
- 'any',
- 'assert',
- 'assertionFailure',
- 'debugPrint',
- 'dump',
- 'fatalError',
- 'getVaList',
- 'isKnownUniquelyReferenced',
- 'max',
- 'min',
- 'numericCast',
- 'pointwiseMax',
- 'pointwiseMin',
- 'precondition',
- 'preconditionFailure',
- 'print',
- 'readLine',
- 'repeatElement',
- 'sequence',
- 'stride',
- 'swap',
- 'swift_unboxFromSwiftValueWithType',
- 'transcode',
- 'type',
- 'unsafeBitCast',
- 'unsafeDowncast',
- 'withExtendedLifetime',
- 'withUnsafeMutablePointer',
- 'withUnsafePointer',
- 'withVaList',
- 'withoutActuallyEscaping',
- 'zip'
- ];
- // Valid first characters for operators.
- const operatorHead = either(
- /[/=\-+!*%<>&|^~?]/,
- /[\u00A1-\u00A7]/,
- /[\u00A9\u00AB]/,
- /[\u00AC\u00AE]/,
- /[\u00B0\u00B1]/,
- /[\u00B6\u00BB\u00BF\u00D7\u00F7]/,
- /[\u2016-\u2017]/,
- /[\u2020-\u2027]/,
- /[\u2030-\u203E]/,
- /[\u2041-\u2053]/,
- /[\u2055-\u205E]/,
- /[\u2190-\u23FF]/,
- /[\u2500-\u2775]/,
- /[\u2794-\u2BFF]/,
- /[\u2E00-\u2E7F]/,
- /[\u3001-\u3003]/,
- /[\u3008-\u3020]/,
- /[\u3030]/
- );
- // Valid characters for operators.
- const operatorCharacter = either(
- operatorHead,
- /[\u0300-\u036F]/,
- /[\u1DC0-\u1DFF]/,
- /[\u20D0-\u20FF]/,
- /[\uFE00-\uFE0F]/,
- /[\uFE20-\uFE2F]/
- // TODO: The following characters are also allowed, but the regex isn't supported yet.
- // /[\u{E0100}-\u{E01EF}]/u
- );
- // Valid operator.
- const operator = concat(operatorHead, operatorCharacter, '*');
- // Valid first characters for identifiers.
- const identifierHead = either(
- /[a-zA-Z_]/,
- /[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,
- /[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,
- /[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,
- /[\u1E00-\u1FFF]/,
- /[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,
- /[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,
- /[\u2C00-\u2DFF\u2E80-\u2FFF]/,
- /[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,
- /[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,
- /[\uFE47-\uFEFE\uFF00-\uFFFD]/ // Should be /[\uFE47-\uFFFD]/, but we have to exclude FEFF.
- // The following characters are also allowed, but the regexes aren't supported yet.
- // /[\u{10000}-\u{1FFFD}\u{20000-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}]/u,
- // /[\u{50000}-\u{5FFFD}\u{60000-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}]/u,
- // /[\u{90000}-\u{9FFFD}\u{A0000-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}]/u,
- // /[\u{D0000}-\u{DFFFD}\u{E0000-\u{EFFFD}]/u
- );
- // Valid characters for identifiers.
- const identifierCharacter = either(
- identifierHead,
- /\d/,
- /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/
- );
- // Valid identifier.
- const identifier = concat(identifierHead, identifierCharacter, '*');
- // Valid type identifier.
- const typeIdentifier = concat(/[A-Z]/, identifierCharacter, '*');
- // Built-in attributes, which are highlighted as keywords.
- // @available is handled separately.
- const keywordAttributes = [
- 'autoclosure',
- concat(/convention\(/, either('swift', 'block', 'c'), /\)/),
- 'discardableResult',
- 'dynamicCallable',
- 'dynamicMemberLookup',
- 'escaping',
- 'frozen',
- 'GKInspectable',
- 'IBAction',
- 'IBDesignable',
- 'IBInspectable',
- 'IBOutlet',
- 'IBSegueAction',
- 'inlinable',
- 'main',
- 'nonobjc',
- 'NSApplicationMain',
- 'NSCopying',
- 'NSManaged',
- concat(/objc\(/, identifier, /\)/),
- 'objc',
- 'objcMembers',
- 'propertyWrapper',
- 'requires_stored_property_inits',
- 'testable',
- 'UIApplicationMain',
- 'unknown',
- 'usableFromInline'
- ];
- // Contextual keywords used in @available and #available.
- const availabilityKeywords = [
- 'iOS',
- 'iOSApplicationExtension',
- 'macOS',
- 'macOSApplicationExtension',
- 'macCatalyst',
- 'macCatalystApplicationExtension',
- 'watchOS',
- 'watchOSApplicationExtension',
- 'tvOS',
- 'tvOSApplicationExtension',
- 'swift'
- ];
- /*
- Language: Swift
- Description: Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
- Author: Steven Van Impe <steven.vanimpe@icloud.com>
- Contributors: Chris Eidhof <chris@eidhof.nl>, Nate Cook <natecook@gmail.com>, Alexander Lichter <manniL@gmx.net>, Richard Gibson <gibson042@github>
- Website: https://swift.org
- Category: common, system
- */
- /** @type LanguageFn */
- function swift(hljs) {
- const WHITESPACE = {
- match: /\s+/,
- relevance: 0
- };
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID411
- const BLOCK_COMMENT = hljs.COMMENT(
- '/\\*',
- '\\*/',
- {
- contains: [ 'self' ]
- }
- );
- const COMMENTS = [
- hljs.C_LINE_COMMENT_MODE,
- BLOCK_COMMENT
- ];
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID413
- // https://docs.swift.org/swift-book/ReferenceManual/zzSummaryOfTheGrammar.html
- const DOT_KEYWORD = {
- className: 'keyword',
- begin: concat(/\./, lookahead(either(...dotKeywords, ...optionalDotKeywords))),
- end: either(...dotKeywords, ...optionalDotKeywords),
- excludeBegin: true
- };
- const KEYWORD_GUARD = {
- // Consume .keyword to prevent highlighting properties and methods as keywords.
- match: concat(/\./, either(...keywords)),
- relevance: 0
- };
- const PLAIN_KEYWORDS = keywords
- .filter(kw => typeof kw === 'string')
- .concat([ "_|0" ]); // seems common, so 0 relevance
- const REGEX_KEYWORDS = keywords
- .filter(kw => typeof kw !== 'string') // find regex
- .concat(keywordTypes)
- .map(keywordWrapper);
- const KEYWORD = {
- variants: [
- {
- className: 'keyword',
- match: either(...REGEX_KEYWORDS, ...optionalDotKeywords)
- }
- ]
- };
- // find all the regular keywords
- const KEYWORDS = {
- $pattern: either(
- /\b\w+/, // regular keywords
- /#\w+/ // number keywords
- ),
- keyword: PLAIN_KEYWORDS
- .concat(numberSignKeywords),
- literal: literals
- };
- const KEYWORD_MODES = [
- DOT_KEYWORD,
- KEYWORD_GUARD,
- KEYWORD
- ];
- // https://github.com/apple/swift/tree/main/stdlib/public/core
- const BUILT_IN_GUARD = {
- // Consume .built_in to prevent highlighting properties and methods.
- match: concat(/\./, either(...builtIns)),
- relevance: 0
- };
- const BUILT_IN = {
- className: 'built_in',
- match: concat(/\b/, either(...builtIns), /(?=\()/)
- };
- const BUILT_INS = [
- BUILT_IN_GUARD,
- BUILT_IN
- ];
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
- const OPERATOR_GUARD = {
- // Prevent -> from being highlighting as an operator.
- match: /->/,
- relevance: 0
- };
- const OPERATOR = {
- className: 'operator',
- relevance: 0,
- variants: [
- {
- match: operator
- },
- {
- // dot-operator: only operators that start with a dot are allowed to use dots as
- // characters (..., ...<, .*, etc). So there rule here is: a dot followed by one or more
- // characters that may also include dots.
- match: `\\.(\\.|${operatorCharacter})+`
- }
- ]
- };
- const OPERATORS = [
- OPERATOR_GUARD,
- OPERATOR
- ];
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_numeric-literal
- // TODO: Update for leading `-` after lookbehind is supported everywhere
- const decimalDigits = '([0-9]_*)+';
- const hexDigits = '([0-9a-fA-F]_*)+';
- const NUMBER = {
- className: 'number',
- relevance: 0,
- variants: [
- // decimal floating-point-literal (subsumes decimal-literal)
- {
- match: `\\b(${decimalDigits})(\\.(${decimalDigits}))?` + `([eE][+-]?(${decimalDigits}))?\\b`
- },
- // hexadecimal floating-point-literal (subsumes hexadecimal-literal)
- {
- match: `\\b0x(${hexDigits})(\\.(${hexDigits}))?` + `([pP][+-]?(${decimalDigits}))?\\b`
- },
- // octal-literal
- {
- match: /\b0o([0-7]_*)+\b/
- },
- // binary-literal
- {
- match: /\b0b([01]_*)+\b/
- }
- ]
- };
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_string-literal
- const ESCAPED_CHARACTER = (rawDelimiter = "") => ({
- className: 'subst',
- variants: [
- {
- match: concat(/\\/, rawDelimiter, /[0\\tnr"']/)
- },
- {
- match: concat(/\\/, rawDelimiter, /u\{[0-9a-fA-F]{1,8}\}/)
- }
- ]
- });
- const ESCAPED_NEWLINE = (rawDelimiter = "") => ({
- className: 'subst',
- match: concat(/\\/, rawDelimiter, /[\t ]*(?:[\r\n]|\r\n)/)
- });
- const INTERPOLATION = (rawDelimiter = "") => ({
- className: 'subst',
- label: "interpol",
- begin: concat(/\\/, rawDelimiter, /\(/),
- end: /\)/
- });
- const MULTILINE_STRING = (rawDelimiter = "") => ({
- begin: concat(rawDelimiter, /"""/),
- end: concat(/"""/, rawDelimiter),
- contains: [
- ESCAPED_CHARACTER(rawDelimiter),
- ESCAPED_NEWLINE(rawDelimiter),
- INTERPOLATION(rawDelimiter)
- ]
- });
- const SINGLE_LINE_STRING = (rawDelimiter = "") => ({
- begin: concat(rawDelimiter, /"/),
- end: concat(/"/, rawDelimiter),
- contains: [
- ESCAPED_CHARACTER(rawDelimiter),
- INTERPOLATION(rawDelimiter)
- ]
- });
- const STRING = {
- className: 'string',
- variants: [
- MULTILINE_STRING(),
- MULTILINE_STRING("#"),
- MULTILINE_STRING("##"),
- MULTILINE_STRING("###"),
- SINGLE_LINE_STRING(),
- SINGLE_LINE_STRING("#"),
- SINGLE_LINE_STRING("##"),
- SINGLE_LINE_STRING("###")
- ]
- };
- // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID412
- const QUOTED_IDENTIFIER = {
- match: concat(/`/, identifier, /`/)
- };
- const IMPLICIT_PARAMETER = {
- className: 'variable',
- match: /\$\d+/
- };
- const PROPERTY_WRAPPER_PROJECTION = {
- className: 'variable',
- match: `\\$${identifierCharacter}+`
- };
- const IDENTIFIERS = [
- QUOTED_IDENTIFIER,
- IMPLICIT_PARAMETER,
- PROPERTY_WRAPPER_PROJECTION
- ];
- // https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
- const AVAILABLE_ATTRIBUTE = {
- match: /(@|#)available/,
- className: "keyword",
- starts: {
- contains: [
- {
- begin: /\(/,
- end: /\)/,
- keywords: availabilityKeywords,
- contains: [
- ...OPERATORS,
- NUMBER,
- STRING
- ]
- }
- ]
- }
- };
- const KEYWORD_ATTRIBUTE = {
- className: 'keyword',
- match: concat(/@/, either(...keywordAttributes))
- };
- const USER_DEFINED_ATTRIBUTE = {
- className: 'meta',
- match: concat(/@/, identifier)
- };
- const ATTRIBUTES = [
- AVAILABLE_ATTRIBUTE,
- KEYWORD_ATTRIBUTE,
- USER_DEFINED_ATTRIBUTE
- ];
- // https://docs.swift.org/swift-book/ReferenceManual/Types.html
- const TYPE = {
- match: lookahead(/\b[A-Z]/),
- relevance: 0,
- contains: [
- { // Common Apple frameworks, for relevance boost
- className: 'type',
- match: concat(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/, identifierCharacter, '+')
- },
- { // Type identifier
- className: 'type',
- match: typeIdentifier,
- relevance: 0
- },
- { // Optional type
- match: /[?!]+/,
- relevance: 0
- },
- { // Variadic parameter
- match: /\.\.\./,
- relevance: 0
- },
- { // Protocol composition
- match: concat(/\s+&\s+/, lookahead(typeIdentifier)),
- relevance: 0
- }
- ]
- };
- const GENERIC_ARGUMENTS = {
- begin: /</,
- end: />/,
- keywords: KEYWORDS,
- contains: [
- ...COMMENTS,
- ...KEYWORD_MODES,
- ...ATTRIBUTES,
- OPERATOR_GUARD,
- TYPE
- ]
- };
- TYPE.contains.push(GENERIC_ARGUMENTS);
- // https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#ID552
- // Prevents element names from being highlighted as keywords.
- const TUPLE_ELEMENT_NAME = {
- match: concat(identifier, /\s*:/),
- keywords: "_|0",
- relevance: 0
- };
- // Matches tuples as well as the parameter list of a function type.
- const TUPLE = {
- begin: /\(/,
- end: /\)/,
- relevance: 0,
- keywords: KEYWORDS,
- contains: [
- 'self',
- TUPLE_ELEMENT_NAME,
- ...COMMENTS,
- ...KEYWORD_MODES,
- ...BUILT_INS,
- ...OPERATORS,
- NUMBER,
- STRING,
- ...IDENTIFIERS,
- ...ATTRIBUTES,
- TYPE
- ]
- };
- // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID362
- // Matches both the keyword func and the function title.
- // Grouping these lets us differentiate between the operator function <
- // and the start of the generic parameter clause (also <).
- const FUNC_PLUS_TITLE = {
- beginKeywords: 'func',
- contains: [
- {
- className: 'title',
- match: either(QUOTED_IDENTIFIER.match, identifier, operator),
- // Required to make sure the opening < of the generic parameter clause
- // isn't parsed as a second title.
- endsParent: true,
- relevance: 0
- },
- WHITESPACE
- ]
- };
- const GENERIC_PARAMETERS = {
- begin: /</,
- end: />/,
- contains: [
- ...COMMENTS,
- TYPE
- ]
- };
- const FUNCTION_PARAMETER_NAME = {
- begin: either(
- lookahead(concat(identifier, /\s*:/)),
- lookahead(concat(identifier, /\s+/, identifier, /\s*:/))
- ),
- end: /:/,
- relevance: 0,
- contains: [
- {
- className: 'keyword',
- match: /\b_\b/
- },
- {
- className: 'params',
- match: identifier
- }
- ]
- };
- const FUNCTION_PARAMETERS = {
- begin: /\(/,
- end: /\)/,
- keywords: KEYWORDS,
- contains: [
- FUNCTION_PARAMETER_NAME,
- ...COMMENTS,
- ...KEYWORD_MODES,
- ...OPERATORS,
- NUMBER,
- STRING,
- ...ATTRIBUTES,
- TYPE,
- TUPLE
- ],
- endsParent: true,
- illegal: /["']/
- };
- const FUNCTION = {
- className: 'function',
- match: lookahead(/\bfunc\b/),
- contains: [
- FUNC_PLUS_TITLE,
- GENERIC_PARAMETERS,
- FUNCTION_PARAMETERS,
- WHITESPACE
- ],
- illegal: [
- /\[/,
- /%/
- ]
- };
- // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID375
- // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID379
- const INIT_SUBSCRIPT = {
- className: 'function',
- match: /\b(subscript|init[?!]?)\s*(?=[<(])/,
- keywords: {
- keyword: "subscript init init? init!",
- $pattern: /\w+[?!]?/
- },
- contains: [
- GENERIC_PARAMETERS,
- FUNCTION_PARAMETERS,
- WHITESPACE
- ],
- illegal: /\[|%/
- };
- // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380
- const OPERATOR_DECLARATION = {
- beginKeywords: 'operator',
- end: hljs.MATCH_NOTHING_RE,
- contains: [
- {
- className: 'title',
- match: operator,
- endsParent: true,
- relevance: 0
- }
- ]
- };
- // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID550
- const PRECEDENCEGROUP = {
- beginKeywords: 'precedencegroup',
- end: hljs.MATCH_NOTHING_RE,
- contains: [
- {
- className: 'title',
- match: typeIdentifier,
- relevance: 0
- },
- {
- begin: /{/,
- end: /}/,
- relevance: 0,
- endsParent: true,
- keywords: [
- ...precedencegroupKeywords,
- ...literals
- ],
- contains: [ TYPE ]
- }
- ]
- };
- // Add supported submodes to string interpolation.
- for (const variant of STRING.variants) {
- const interpolation = variant.contains.find(mode => mode.label === "interpol");
- // TODO: Interpolation can contain any expression, so there's room for improvement here.
- interpolation.keywords = KEYWORDS;
- const submodes = [
- ...KEYWORD_MODES,
- ...BUILT_INS,
- ...OPERATORS,
- NUMBER,
- STRING,
- ...IDENTIFIERS
- ];
- interpolation.contains = [
- ...submodes,
- {
- begin: /\(/,
- end: /\)/,
- contains: [
- 'self',
- ...submodes
- ]
- }
- ];
- }
- return {
- name: 'Swift',
- keywords: KEYWORDS,
- contains: [
- ...COMMENTS,
- FUNCTION,
- INIT_SUBSCRIPT,
- {
- className: 'class',
- beginKeywords: 'struct protocol class extension enum',
- end: '\\{',
- excludeEnd: true,
- keywords: KEYWORDS,
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {
- begin: /[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/
- }),
- ...KEYWORD_MODES
- ]
- },
- OPERATOR_DECLARATION,
- PRECEDENCEGROUP,
- {
- beginKeywords: 'import',
- end: /$/,
- contains: [ ...COMMENTS ],
- relevance: 0
- },
- ...KEYWORD_MODES,
- ...BUILT_INS,
- ...OPERATORS,
- NUMBER,
- STRING,
- ...IDENTIFIERS,
- ...ATTRIBUTES,
- TYPE,
- TUPLE
- ]
- };
- }
- module.exports = swift;
|