/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
vscode-ng-language-service/syntaxes/src/expression.ts
1 032 строки
31 KB
Matthieu Riegler
fix(vscode-extension): Highlight function calls with optional chaining
10 фев 2026, 20:42
10 фев 2026, 20:42
4f8d399
Код
Авторство
О чём код?
/*! * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import {GrammarDefinition} from './types'; export const Expression: GrammarDefinition = { scopeName: 'expression.ng', injectionSelector: 'L:text.html -comment', patterns: [{include: '#ngExpression'}], repository: { ngExpression: { name: 'meta.expression.ng', patterns: [ { include: '#string', }, { include: '#literal', }, { include: '#arrowFunction', }, { include: '#ternaryExpression', }, { include: '#expressionOperator', }, { include: '#functionCall', }, { include: '#identifiers', }, { include: '#parenExpression', }, { include: '#punctuationComma', }, { include: '#punctuationSemicolon', }, { include: '#punctuationAccessor', }, ], }, arrayLiteral: { name: 'meta.array.literal.ts', begin: /\[/, beginCaptures: { 0: { name: 'meta.brace.square.ts', }, }, end: /\]/, endCaptures: { 0: { name: 'meta.brace.square.ts', }, }, patterns: [ { include: '#ngExpression', }, { include: '#punctuationComma', }, ], }, booleanLiteral: { patterns: [ { name: 'constant.language.boolean.true.ts', match: /(?<!\.|\$)\btrue\b(?!\$)/, }, { name: 'constant.language.boolean.false.ts', match: /(?<!\.|\$)\bfalse\b(?!\$)/, }, ], }, expressionOperator: { patterns: [ { match: /((?<!\|)\|(?!\|))\s?([a-zA-Z0-9\-\_\$]*)/, captures: { 1: { name: 'keyword.operator.logical.ts', }, 2: { name: 'entity.name.function.pipe.ng', }, }, }, { name: 'storage.type.ts', match: /(?<!\.|\$)\b(let)\b(?!\$)/, }, { name: 'keyword.control.flow.ts', match: /(?<!\.|\$)\b(await)\b(?!\$)/, }, { name: 'keyword.operator.expression.delete.ts', match: /(?<!\.|\$)\bdelete\b(?!\$)/, }, { name: 'keyword.operator.expression.in.ts', match: /(?<!\.|\$)\bin\b(?!\$)/, }, { name: 'keyword.operator.expression.of.ts', match: /(?<!\.|\$)\bof\b(?!\$)/, }, { name: 'keyword.control.if.ts', match: /(?<!\.|\$)\bif\b(?!\$)/, }, { name: 'keyword.control.else.ts', match: /(?<!\.|\$)\belse\b(?!\$)/, }, { name: 'keyword.control.then.ts', match: /(?<!\.|\$)\bthen\b(?!\$)/, }, { name: 'keyword.operator.expression.instanceof.ts', match: /(?<!\.|\$)\binstanceof\b(?!\$)/, }, { name: 'keyword.operator.new.ts', match: /(?<!\.|\$)\bnew\b(?!\$)/, }, { name: 'keyword.operator.expression.void.ts', match: /(?<!\.|\$)\bvoid\b(?!\$)/, }, { begin: /(?<!\.|\$)\bas\b(?!\$)/, beginCaptures: { 0: { name: 'storage.type.as.ts', }, }, end: /(?=$|"|'|[;,:})\]])/, patterns: [ { include: '#type', }, ], }, { name: 'keyword.operator.assignment.compound.ts', match: /\*=|(?<!\()\/=|%=|\+=|\-=/, }, { name: 'keyword.operator.assignment.compound.bitwise.ts', match: /\&=|\^=|<<=|>>=|>>>=|\|=/, }, { name: 'keyword.operator.bitwise.shift.ts', match: /<<|>>>|>>/, }, { name: 'keyword.operator.spread.ts', match: /\.\.\./, }, { name: 'keyword.operator.comparison.ts', match: /===|!==|==|!=/, }, { name: 'keyword.operator.relational.ts', match: /<=|>=|<>|<|>/, }, { name: 'keyword.operator.logical.ts', match: /\!|&&|\?\?|\|\|/, }, { name: 'keyword.operator.bitwise.ts', match: /\&|~|\^|\|/, }, { name: 'keyword.operator.assignment.ts', match: /\=/, }, { name: 'keyword.operator.decrement.ts', match: /--/, }, { name: 'keyword.operator.increment.ts', match: /\+\+/, }, { name: 'keyword.operator.arithmetic.ts', match: /\%|\*|\/|-|\+/, }, { match: /(?<=[_$[:alnum:]])\s*(\/)(?![\/*])/, captures: { 1: { name: 'keyword.operator.arithmetic.ts', }, }, }, { include: '#typeofOperator', }, ], }, functionCall: { begin: /(?=(\??\.\s*)?([_$[:alpha:]][_$[:alnum:]]*)\s*(<([^<>]|\<[^<>]+\>)+>\s*)?(\?\.\s*)?\()/, end: /(?<=\))(?!(\??\.\s*)?([_$[:alpha:]][_$[:alnum:]]*)\s*(<([^<>]|\<[^<>]+\>)+>\s*)?(\?\.\s*)?\()/, patterns: [ { name: 'punctuation.accessor.ts', match: /\?/, }, { name: 'punctuation.accessor.ts', match: /\./, }, { name: 'entity.name.function.ts', match: /([_$[:alpha:]][_$[:alnum:]]*)/, }, { name: 'meta.type.parameters.ts', begin: /\</, beginCaptures: { 0: { name: 'punctuation.definition.typeparameters.begin.ts', }, }, end: /\>/, endCaptures: { 0: { name: 'punctuation.definition.typeparameters.end.ts', }, }, patterns: [ { include: '#type', }, { include: '#punctuationComma', }, ], }, { include: '#parenExpression', }, ], }, functionParameters: { name: 'meta.parameters.ts', begin: /\(/, beginCaptures: { 0: { name: 'punctuation.definition.parameters.begin.ts', }, }, end: /\)/, endCaptures: { 0: { name: 'punctuation.definition.parameters.end.ts', }, }, patterns: [ { include: '#decorator', }, { include: '#parameterName', }, { include: '#variableInitializer', }, { name: 'punctuation.separator.parameter.ts', match: /,/, }, ], }, identifiers: { patterns: [ { name: 'support.class.ts', match: /([_$[:alpha:]][_$[:alnum:]]*)(?=\s*\.\s*prototype\b(?!\$))/, }, { match: '(?x)([?!]?\\.)\\s*(?:\n([[:upper:]][_$[:digit:][:upper:]]*)|\n([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)', captures: { 1: { name: 'punctuation.accessor.ts', }, 2: { name: 'constant.other.object.property.ts', }, 3: { name: 'variable.other.object.property.ts', }, }, }, { match: '(?x)(?:([?!]?\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*((async\\s+)|(function\\s*[(<])|(function\\s+)|([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))', captures: { 1: { name: 'punctuation.accessor.ts', }, 2: { name: 'entity.name.function.ts', }, }, }, { match: '([?!]?\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])', captures: { 1: { name: 'punctuation.accessor.ts', }, 2: { name: 'constant.other.property.ts', }, }, }, { match: '([?!]?\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)', captures: { 1: { name: 'punctuation.accessor.ts', }, 2: { name: 'variable.other.property.ts', }, }, }, { match: '(?x)(?:\n([[:upper:]][_$[:digit:][:upper:]]*)|\n([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)', captures: { 1: { name: 'constant.other.object.ts', }, 2: { name: 'variable.other.object.ts', }, }, }, { name: 'constant.character.other', match: '([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])', }, { name: 'variable.other.readwrite.ts', match: '[_$[:alpha:]][_$[:alnum:]]*', }, ], }, literal: { name: 'literal.ts', patterns: [ { include: '#numericLiteral', }, { include: '#booleanLiteral', }, { include: '#nullLiteral', }, { include: '#undefinedLiteral', }, { include: '#numericConstantLiteral', }, { include: '#arrayLiteral', }, { include: '#thisLiteral', }, ], }, nullLiteral: { name: 'constant.language.null.ts', match: /(?<!\.|\$)\bnull\b(?!\$)/, }, numericLiteral: { patterns: [ { name: 'constant.numeric.hex.ts', match: /\b(?<!\$)0(x|X)[0-9a-fA-F]+\b(?!\$)/, }, { name: 'constant.numeric.binary.ts', match: /\b(?<!\$)0(b|B)[01]+\b(?!\$)/, }, { name: 'constant.numeric.octal.ts', match: /\\b(?<!\$)0(o|O)?[0-7]+\b(?!\$)/, }, { match: '(?x)\n(?<!\\$)(?:\n(?:\\b[0-9]+(\\.)[0-9]+[eE][+-]?[0-9]+\\b)|#1.1E+3\n(?:\\b[0-9]+(\\.)[eE][+-]?[0-9]+\\b)|#1.E+3\n(?:\\B(\\.)[0-9]+[eE][+-]?[0-9]+\\b)|#.1E+3\n(?:\\b[0-9]+[eE][+-]?[0-9]+\\b)|#1E+3(?:\\b[0-9]+(\\.)[0-9]+\\b)|#1.1\n(?:\\b[0-9]+(\\.)\\B)|#1.\n(?:\\B(\\.)[0-9]+\\b)|#.1\n (?:\\b[0-9]+\\b(?!\\.))#1\n)(?!\\$)', captures: { 0: { name: 'constant.numeric.decimal.ts', }, 1: { name: 'meta.delimiter.decimal.period.ts', }, 2: { name: 'meta.delimiter.decimal.period.ts', }, 3: { name: 'meta.delimiter.decimal.period.ts', }, 4: { name: 'meta.delimiter.decimal.period.ts', }, 5: { name: 'meta.delimiter.decimal.period.ts', }, 6: { name: 'meta.delimiter.decimal.period.ts', }, }, }, ], }, numericConstantLiteral: { patterns: [ { name: 'constant.language.nan.ts', match: /(?<!\.|\$)\bNaN\b(?!\$)/, }, { name: 'constant.language.infinity.ts', match: /(?<!\.|\$)\bInfinity\b(?!\$)/, }, ], }, parameterName: { patterns: [ { match: '(?x)(?:\\s*\\b(readonly)\\s+)?(?:\\s*\\b(public|private|protected)\\s+)?(\\.\\.\\.)?\\s*(?<!=|:)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\??)(?=\\s* (=\\s*( (async\\s+) | (function\\s*[(<]) | (function\\s+) | ([_$[:alpha:]][_$[:alnum:]]*\\s*=>) | ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)) ) | (:\\s*( (<) | ([(]\\s*( ([)]) | (\\.\\.\\.) | ([_$[:alnum:]]+\\s*( ([:,?=])| ([)]\\s*=>) )) ))) ))', captures: { 1: { name: 'storage.modifier.ts', }, 2: { name: 'storage.modifier.ts', }, 3: { name: 'keyword.operator.rest.ts', }, 4: { name: 'entity.name.function.ts', }, 5: { name: 'keyword.operator.optional.ts', }, }, }, { match: /(?:\s*\b(readonly)\s+)?(?:\s*\b(public|private|protected)\s+)?(\.\.\.)?\s*(?<!=|:)([_$[:alpha:]][_$[:alnum:]]*)\s*(\??)/, captures: { 1: { name: 'storage.modifier.ts', }, 2: { name: 'storage.modifier.ts', }, 3: { name: 'keyword.operator.rest.ts', }, 4: { name: 'variable.parameter.ts', }, 5: { name: 'keyword.operator.optional.ts', }, }, }, ], }, parenExpression: { begin: /\(/, beginCaptures: { 0: { name: 'meta.brace.round.ts', }, }, end: /\)/, endCaptures: { 0: { name: 'meta.brace.round.ts', }, }, patterns: [ { include: '#ngExpression', }, { include: '#punctuationComma', }, ], }, punctuationAccessor: { name: 'punctuation.accessor.ts', match: /\?\.|\!\.|\./, }, punctuationComma: { name: 'punctuation.separator.comma.ts', match: /,/, }, punctuationSemicolon: { name: 'punctuation.terminator.statement.ts', match: /;/, }, qstringDouble: { name: 'string.quoted.double.ts', begin: /"/, beginCaptures: { 0: { name: 'punctuation.definition.string.begin.ts', }, }, end: /(")|((?:[^\\\n])$)/, endCaptures: { 1: { name: 'punctuation.definition.string.end.ts', }, 2: { name: 'invalid.illegal.newline.ts', }, }, patterns: [ { include: '#stringCharacterEscape', }, ], }, qstringSingle: { name: 'string.quoted.single.ts', begin: /'/, beginCaptures: { 0: { name: 'punctuation.definition.string.begin.ts', }, }, end: /(\')|((?:[^\\\n])$)/, endCaptures: { 1: { name: 'punctuation.definition.string.end.ts', }, 2: { name: 'invalid.illegal.newline.ts', }, }, patterns: [ { include: '#stringCharacterEscape', }, ], }, // Via // https://github.com/microsoft/vscode-typescript-next/blob/bb6c015fdfe8c80e2f24bd83bb70d4d6581b0708/syntaxes/TypeScript.tmLanguage.json templateLiteral: { patterns: [ {include: '#templateLiteralCall'}, { contentName: 'string.template.ts', begin: /([_$[:alpha:]][_$[:alnum:]]*)?(`)/, beginCaptures: { 1: {name: 'entity.name.function.tagged-template.ts'}, 2: { name: 'string.template.ts punctuation.definition.string.template.begin.ts', }, }, end: /`/, endCaptures: { 0: { name: 'string.template.ts punctuation.definition.string.template.end.ts', }, }, patterns: [ {include: '#templateLiteralSubstitutionElement'}, {include: '#stringCharacterEscape'}, ], }, ], }, templateLiteralCall: { patterns: [ { begin: /(?=(([_$[:alpha:]][_$[:alnum:]]*\s*\??\.\s*)*|(\??\.\s*)?)([_$[:alpha:]][_$[:alnum:]]*)(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?<!=)\>))*(?<!=)\>)*(?<!=)>\s*)?`)/, end: /(?=`)/, patterns: [ { begin: /(?=(([_$[:alpha:]][_$[:alnum:]]*\s*\??\.\s*)*|(\??\.\s*)?)([_$[:alpha:]][_$[:alnum:]]*))/, end: /(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?<!=)\>))*(?<!=)\>)*(?<!=)>\s*)?`)/, patterns: [ {include: '#support-function-call-identifiers'}, { name: 'entity.name.function.tagged-template.ts', match: /([_$[:alpha:]][_$[:alnum:]]*)/, }, ], }, {include: '#typeArguments'}, ], }, { begin: /([_$[:alpha:]][_$[:alnum:]]*)?\s*(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?<!=)\>))*(?<!=)\>)*(?<!=)>\s*)`)/, beginCaptures: {1: {name: 'entity.name.function.tagged-template.ts'}}, end: /(?=`)/, patterns: [{include: '#typeArguments'}], }, ], }, templateLiteralSubstitutionElement: { name: 'meta.template.expression.ts', begin: /\${/, beginCaptures: {0: {name: 'punctuation.definition.template-expression.begin.ts'}}, end: /}/, endCaptures: {0: {name: 'punctuation.definition.template-expression.end.ts'}}, patterns: [{include: '#ngExpression'}], contentName: 'meta.embedded.line.ts', }, typeArguments: { name: 'meta.type.parameters.ts', begin: /</, beginCaptures: {0: {name: 'punctuation.definition.typeparameters.begin.ts'}}, end: />/, endCaptures: {0: {name: 'punctuation.definition.typeparameters.end.ts'}}, patterns: [{include: '#typeArgumentsBody'}], }, stringCharacterEscape: { name: 'constant.character.escape.ts', match: /\\(x\h{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)/, }, // Derived from // https://github.com/microsoft/vscode-typescript-next/blob/849bce9ce68c4b87e6e1de0c31573ff376c7078d/syntaxes/TypeScript.tmLanguage.json#L2855-L2873 ternaryExpression: { // 1. negative lookahead (?!\?\.\s*[^[:digit:]]) ensures safe navigation does not match // 2. match the ternary question mark with (\?) // 3. negative lookahead (?!\?) ensures nullish coalesce does not match begin: /(?!\?\.\s*[^[:digit:]])(\?)(?!\?)/, beginCaptures: { 1: { name: 'keyword.operator.ternary.ts', }, }, end: /\s*(:)/, endCaptures: { 1: { name: 'keyword.operator.ternary.ts', }, }, patterns: [ { include: '#ngExpression', }, ], }, thisLiteral: { name: 'variable.language.this.ts', match: /(?<!\.|\$)\bthis\b(?!\$)/, }, string: { patterns: [ { include: '#qstringSingle', }, { include: '#qstringDouble', }, { include: '#templateLiteral', }, ], }, typeAnnotation: { name: 'meta.type.annotation.ts', begin: /:/, beginCaptures: { 0: { name: 'keyword.operator.type.annotation.ts', }, }, end: /(?=$|[,);\}\]]|\/\/|")|(?==[^>])|(?<=[\}>\]\)]|[_$[:alpha:]])\s*(?=\{)/, patterns: [ { include: '#type', }, ], }, typeBuiltinLiterals: { name: 'support.type.builtin.ts', match: /(?<!\.|\$)\b(this|true|false|undefined|null)\b(?!\$)/, }, typeFnTypeParameters: { patterns: [ { name: 'meta.type.constructor.ts', match: /(?<!\.|\$)\b(new)\b(?=\s*\<)/, captures: { 1: { name: 'keyword.control.new.ts', }, }, }, { name: 'meta.type.constructor.ts', begin: /(?<!\.|\$)\b(new)\b\s*(?=\()/, beginCaptures: { 1: { name: 'keyword.control.new.ts', }, }, end: /(?<=\))/, patterns: [ { include: '#functionParameters', }, ], }, { name: 'meta.type.function.ts', include: '#typeofOperator', begin: /(?<=\>)\s*(?=\()/, end: /(?<=\))/, patterns: [ { include: '#functionParameters', }, ], }, { name: 'meta.type.function.ts', begin: '(?x)((?=[(]\\s*(([)])|(\\.\\.\\.)|([_$[:alnum:]]+\\s*(([:,?=])|([)]\\s*=>))))))', end: /(?<=\))/, patterns: [ { include: '#functionParameters', }, ], }, ], }, typeName: { patterns: [ { match: /([_$[:alpha:]][_$[:alnum:]]*)\s*([?!]?\.)/, captures: { 1: { name: 'entity.name.type.module.ts', }, 2: { name: 'punctuation.accessor.ts', }, }, }, { name: 'entity.name.type.ts', match: /[_$[:alpha:]][_$[:alnum:]]*/, }, ], }, typeObjectMembers: { patterns: [ { include: '#typeAnnotation', }, { include: '#punctuationComma', }, { include: '#punctuationSemicolon', }, ], }, typeObject: { name: 'meta.object.type.ts', begin: /\{/, beginCaptures: { 0: { name: 'punctuation.definition.block.ts', }, }, end: /\}/, endCaptures: { 0: { name: 'punctuation.definition.block.ts', }, }, patterns: [ { include: '#typeObjectMembers', }, ], }, typeOperators: { patterns: [ { include: '#typeofOperator', }, { name: 'keyword.operator.type.ts', match: /[&|]/, }, { name: 'keyword.operator.expression.keyof.ts', match: /(?<!\.|\$)\bkeyof\b(?!\$)/, }, ], }, typeParenOrFunctionParameters: { name: 'meta.type.paren.cover.ts', begin: /\(/, beginCaptures: { 0: { name: 'meta.brace.round.ts', }, }, end: /\)/, endCaptures: { 0: { name: 'meta.brace.round.ts', }, }, patterns: [ { include: '#type', }, { include: '#functionParameters', }, ], }, typeTuple: { name: 'meta.type.tuple.ts', begin: /\[/, beginCaptures: { 0: { name: 'meta.brace.square.ts', }, }, end: /\]/, endCaptures: { 0: { name: 'meta.brace.square.ts', }, }, patterns: [ { include: '#type', }, { include: '#punctuationComma', }, ], }, typeArgumentsBody: { patterns: [ { match: /(?<![_$[:alnum:]])(?:(?<=\.\.\.)|(?<!\.))(_)(?![_$[:alnum:]])(?:(?=\.\.\.)|(?!\.))/, captures: {0: {name: 'keyword.operator.type.ts'}}, }, {include: '#type'}, {include: '#punctuationComma'}, ], }, type: { name: 'meta.type.ts', patterns: [ { include: '#string', }, { include: '#numericLiteral', }, { include: '#typeBuiltinLiterals', }, { include: '#typeTuple', }, { include: '#typeObject', }, { include: '#typeOperators', }, { include: '#typeFnTypeParameters', }, { include: '#typeParenOrFunctionParameters', }, { include: '#typeName', }, ], }, typeofOperator: { name: 'keyword.operator.expression.typeof.ts', match: /(?<!\.|\$)\btypeof\b(?!\$)/, }, undefinedLiteral: { name: 'constant.language.undefined.ts', match: /(?<!\.|\$)\bundefined\b(?!\$)/, }, variableInitializer: { begin: /(?<!=|!)(=)(?!=)/, beginCaptures: { 1: { name: 'keyword.operator.assignment.ts', }, }, end: /(?=$|[,);}\]])/, patterns: [ { include: '#ngExpression', }, ], }, // Via https://github.com/microsoft/vscode-typescript-next/blob/2db036c6a8c4000dbe8cfc591512b1a6f4e666d0/syntaxes/TypeScript.tmLanguage.json#L1509 arrowFunction: { patterns: [ { name: 'meta.arrow.ts', match: /(?:(?<![_$[:alnum:]])(?:(?<=\.\.\.)|(?<!\.))\basync\s+)?([_$[:alpha:]][_$[:alnum:]]*)\s*(?==>)/, captures: { 1: { name: 'variable.parameter.ts', }, }, }, { name: 'meta.arrow.ts', begin: '(?x) (?:\n (?<![_$[:alnum:]])(?:(?<=\\.\\.\\.)|(?<!\\.))(\\basync)\n)? ((?<![})!\\]])\\s*\n (?=\n # sure shot arrow functions even if => is on new line\n(\n (<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)?\n [(]\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n\n# arrow function possible to detect only with => on same line\n(\n (<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<]|\\<\\s*(((const\\s+)?[_$[:alpha:]])|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\]))([^=<>]|=[^<])*\\>)*\\>)*>\\s*)? # typeparameters\n \\(\\s*(\\/\\*([^\\*]|(\\*[^\\/]))*\\*\\/\\s*)*(([_$[:alpha:]]|(\\{([^\\{\\}]|(\\{([^\\{\\}]|\\{[^\\{\\}]*\\})*\\}))*\\})|(\\[([^\\[\\]]|(\\[([^\\[\\]]|\\[[^\\[\\]]*\\])*\\]))*\\])|(\\.\\.\\.\\s*[_$[:alpha:]]))([^()\\\'\\"\\`]|(\\(([^\\(\\)]|(\\(([^\\(\\)]|\\([^\\(\\)]*\\))*\\)))*\\))|(\\\'([^\\\'\\\\]|\\\\.)*\\\')|(\\"([^\\"\\\\]|\\\\.)*\\")|(\\`([^\\`\\\\]|\\\\.)*\\`))*)?\\) # parameters\n (\\s*:\\s*([^<>\\(\\)\\{\\}]|\\<([^<>]|\\<([^<>]|\\<[^<>]+\\>)+\\>)+\\>|\\([^\\(\\)]+\\)|\\{[^\\{\\}]+\\})+)? # return type\n \\s*=> # arrow operator\n)\n )\n)', end: '(?==>|\\{|(^\\s*(export|function|class|interface|let|var|(?:\\busing(?=\\s+(?!in\\b|of\\b(?!\\s*(?:of\\b|=)))[_$[:alpha:]])\\b)|(?:\\bawait\\s+(?:\\busing(?=\\s+(?!in\\b|of\\b(?!\\s*(?:of\\b|=)))[_$[:alpha:]])\\b)\\b)|const|import|enum|namespace|module|type|abstract|declare)\\s+))', patterns: [ { include: '#functionParameters', }, ], }, { name: 'meta.arrow.ts', begin: '=>', beginCaptures: { '0': { name: 'storage.type.function.arrow.ts', }, }, end: '((?<=\\}|\\S)(?<!=>)|((?!\\{)(?=\\S)))(?!\\/[\\/\\*])', patterns: [ { include: '#ngExpression', }, ], }, ], }, }, };