Skip to content

Commit da7967a

Browse files
Added basic support for parsing/emitting type arguments in tagged template expressions.
1 parent 60b6d3f commit da7967a

3 files changed

Lines changed: 29 additions & 9 deletions

File tree

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,7 @@ namespace ts {
14621462

14631463
function emitTaggedTemplateExpression(node: TaggedTemplateExpression) {
14641464
emitExpression(node.tag);
1465+
emitTypeArguments(node, node.typeArguments);
14651466
writeSpace();
14661467
emitExpression(node.template);
14671468
}

src/compiler/parser.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ namespace ts {
223223
visitNodes(cbNode, cbNodes, (<CallExpression>node).arguments);
224224
case SyntaxKind.TaggedTemplateExpression:
225225
return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
226+
visitNodes(cbNode, cbNodes, (<TaggedTemplateExpression>node).typeArguments) ||
226227
visitNode(cbNode, (<TaggedTemplateExpression>node).template);
227228
case SyntaxKind.TypeAssertionExpression:
228229
return visitNode(cbNode, (<TypeAssertion>node).type) ||
@@ -4362,18 +4363,28 @@ namespace ts {
43624363
continue;
43634364
}
43644365

4365-
if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) {
4366-
const tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expression.pos);
4367-
tagExpression.tag = expression;
4368-
tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
4369-
? <NoSubstitutionTemplateLiteral>parseLiteralNode()
4370-
: parseTemplateExpression();
4371-
expression = finishNode(tagExpression);
4366+
if (isTemplateStartOfTaggedTemplate()) {
4367+
expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined);
43724368
continue;
43734369
}
43744370

43754371
return <MemberExpression>expression;
43764372
}
4373+
4374+
}
4375+
4376+
function isTemplateStartOfTaggedTemplate() {
4377+
return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead;
4378+
}
4379+
4380+
function parseTaggedTemplateRest(tag: LeftHandSideExpression, typeArguments: NodeArray<TypeNode> | undefined) {
4381+
const tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, tag.pos);
4382+
tagExpression.tag = tag;
4383+
tagExpression.typeArguments = typeArguments;
4384+
tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
4385+
? <NoSubstitutionTemplateLiteral>parseLiteralNode()
4386+
: parseTemplateExpression();
4387+
return finishNode(tagExpression);
43774388
}
43784389

43794390
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
@@ -4389,6 +4400,11 @@ namespace ts {
43894400
return expression;
43904401
}
43914402

4403+
if (isTemplateStartOfTaggedTemplate()) {
4404+
expression = parseTaggedTemplateRest(expression, typeArguments);
4405+
continue;
4406+
}
4407+
43924408
const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
43934409
callExpr.expression = expression;
43944410
callExpr.typeArguments = typeArguments;
@@ -4436,8 +4452,10 @@ namespace ts {
44364452
function canFollowTypeArgumentsInExpression(): boolean {
44374453
switch (token()) {
44384454
case SyntaxKind.OpenParenToken: // foo<x>(
4439-
// this case are the only case where this token can legally follow a type argument
4440-
// list. So we definitely want to treat this as a type arg list.
4455+
case SyntaxKind.NoSubstitutionTemplateLiteral: // foo<T> `...`
4456+
case SyntaxKind.TemplateHead: // foo<T> `...${100}...`
4457+
// these are the only tokens can legally follow a type argument
4458+
// list. So we definitely want to treat them as type arg lists.
44414459

44424460
case SyntaxKind.DotToken: // foo<x>.
44434461
case SyntaxKind.CloseParenToken: // foo<x>)

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,7 @@ namespace ts {
17261726
export interface TaggedTemplateExpression extends MemberExpression {
17271727
kind: SyntaxKind.TaggedTemplateExpression;
17281728
tag: LeftHandSideExpression;
1729+
typeArguments?: NodeArray<TypeNode>;
17291730
template: TemplateLiteral;
17301731
}
17311732

0 commit comments

Comments
 (0)