Skip to content

Commit b95753e

Browse files
crisbetothePunderWoman
authored andcommitted
fix(vscode-extension): add syntax highlighting for arrow functions
Updates the syntax definition to handle arrow functions. The definition is largely based on TypeScript's own syntax highlighting since it's quite complex.
1 parent c70a6a6 commit b95753e

4 files changed

Lines changed: 348 additions & 0 deletions

File tree

vscode-ng-language-service/syntaxes/expression.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
{
1717
"include": "#literal"
1818
},
19+
{
20+
"include": "#arrowFunction"
21+
},
1922
{
2023
"include": "#ternaryExpression"
2124
},
@@ -971,6 +974,44 @@
971974
"include": "#ngExpression"
972975
}
973976
]
977+
},
978+
"arrowFunction": {
979+
"patterns": [
980+
{
981+
"name": "meta.arrow.ts",
982+
"match": "(?:(?<![_$[:alnum:]])(?:(?<=\\.\\.\\.)|(?<!\\.))\\basync\\s+)?([_$[:alpha:]][_$[:alnum:]]*)\\s*(?==>)",
983+
"captures": {
984+
"1": {
985+
"name": "variable.parameter.ts"
986+
}
987+
}
988+
},
989+
{
990+
"name": "meta.arrow.ts",
991+
"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)",
992+
"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+))",
993+
"patterns": [
994+
{
995+
"include": "#functionParameters"
996+
}
997+
]
998+
},
999+
{
1000+
"name": "meta.arrow.ts",
1001+
"begin": "=>",
1002+
"beginCaptures": {
1003+
"0": {
1004+
"name": "storage.type.function.arrow.ts"
1005+
}
1006+
},
1007+
"end": "((?<=\\}|\\S)(?<!=>)|((?!\\{)(?=\\S)))(?!\\/[\\/\\*])",
1008+
"patterns": [
1009+
{
1010+
"include": "#ngExpression"
1011+
}
1012+
]
1013+
}
1014+
]
9741015
}
9751016
}
9761017
}

vscode-ng-language-service/syntaxes/src/expression.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ export const Expression: GrammarDefinition = {
2222
{
2323
include: '#literal',
2424
},
25+
{
26+
include: '#arrowFunction',
27+
},
2528
{
2629
include: '#ternaryExpression',
2730
},
@@ -982,5 +985,47 @@ export const Expression: GrammarDefinition = {
982985
},
983986
],
984987
},
988+
989+
// Via https://github.com/microsoft/vscode-typescript-next/blob/2db036c6a8c4000dbe8cfc591512b1a6f4e666d0/syntaxes/TypeScript.tmLanguage.json#L1509
990+
arrowFunction: {
991+
patterns: [
992+
{
993+
name: 'meta.arrow.ts',
994+
match:
995+
/(?:(?<![_$[:alnum:]])(?:(?<=\.\.\.)|(?<!\.))\basync\s+)?([_$[:alpha:]][_$[:alnum:]]*)\s*(?==>)/,
996+
captures: {
997+
1: {
998+
name: 'variable.parameter.ts',
999+
},
1000+
},
1001+
},
1002+
{
1003+
name: 'meta.arrow.ts',
1004+
begin:
1005+
'(?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)',
1006+
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+))',
1007+
patterns: [
1008+
{
1009+
include: '#functionParameters',
1010+
},
1011+
],
1012+
},
1013+
{
1014+
name: 'meta.arrow.ts',
1015+
begin: '=>',
1016+
beginCaptures: {
1017+
'0': {
1018+
name: 'storage.type.function.arrow.ts',
1019+
},
1020+
},
1021+
end: '((?<=\\}|\\S)(?<!=>)|((?!\\{)(?=\\S)))(?!\\/[\\/\\*])',
1022+
patterns: [
1023+
{
1024+
include: '#ngExpression',
1025+
},
1026+
],
1027+
},
1028+
],
1029+
},
9851030
},
9861031
};

vscode-ng-language-service/syntaxes/test/data/expression.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,16 @@
104104

105105
<!-- Rest -->
106106
{{ someFn(1, ...foo, 2, ...bar, 3, ...baz) }}
107+
108+
<!-- Arrow functions -->
109+
{{ foo => foo + 1 }}
110+
{{ (foo, bar, baz) => foo + bar + baz }}
111+
{{ (foo, bar) => [foo, bar, 1, 2] }}
112+
{{ (foo, bar) => ({foo: 1, bar: 2}) }}
113+
{{ a => (b, c) => (d, e) => f => a + b + c + d + e + f }}
114+
{{ ((a, b) => a * b)(2, 3) }}
115+
{{ [a => a + 1, (b, c) => b + c] }}
116+
{{ (a, b) =>
117+
a / b + 123
118+
}}
119+
{{ someSignal.update(prev => prev + 1) }}

0 commit comments

Comments
 (0)