Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 80c5cab

Browse files
committed
Emit additional parenthesis for casts in template expressions
This is required by closure ES6 to not produce an error. Note: In the current version of tsickle, type comments in interpolations are elided because of #411. In the upcoming transformer version, this is fixed though.
1 parent b298d95 commit 80c5cab

File tree

7 files changed

+37
-2
lines changed

7 files changed

+37
-2
lines changed

src/tsickle.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ class Annotator extends ClosureRewriter {
525525
private generatedExports = new Set<string>();
526526
/** DecoratorClassVisitor when lowering decorators while closure annotating */
527527
private currentDecoratorConverter: DecoratorClassVisitor|undefined;
528+
529+
private templateSpanStackCount = 0;
528530
private polymerBehaviorStackCount = 0;
529531

530532
constructor(
@@ -719,10 +721,21 @@ class Annotator extends ClosureRewriter {
719721
return true;
720722
case ts.SyntaxKind.EnumDeclaration:
721723
return this.maybeProcessEnum(node as ts.EnumDeclaration);
724+
case ts.SyntaxKind.TemplateSpan:
725+
this.templateSpanStackCount++;
726+
this.writeNode(node);
727+
this.templateSpanStackCount--;
728+
return true;
722729
case ts.SyntaxKind.TypeAssertionExpression:
723730
case ts.SyntaxKind.AsExpression:
724731
// Both of these cases are AssertionExpressions.
725732
const typeAssertion = node as ts.AssertionExpression;
733+
// When using a type casts in template expressions,
734+
// closure requires another pair of parens, otherwise it will
735+
// complain with "Misplaced type annotation. Type annotations are not allowed here."
736+
if (this.templateSpanStackCount > 0) {
737+
this.emit('(');
738+
}
726739
this.emitJSDocType(typeAssertion);
727740
// When TypeScript emits JS, it removes one layer of "redundant"
728741
// parens, but we need them for the Closure type assertion. Work
@@ -732,6 +745,9 @@ class Annotator extends ClosureRewriter {
732745
this.emit('((');
733746
this.writeNode(node);
734747
this.emit('))');
748+
if (this.templateSpanStackCount > 0) {
749+
this.emit(')');
750+
}
735751
return true;
736752
case ts.SyntaxKind.NonNullExpression:
737753
const nnexpr = node as ts.NonNullExpression;
@@ -745,11 +761,18 @@ class Annotator extends ClosureRewriter {
745761
typeCopy.types = nonNullUnion;
746762
type = typeCopy;
747763
}
764+
// See comment above.
765+
if (this.templateSpanStackCount > 0) {
766+
this.emit('(');
767+
}
748768
this.emitJSDocType(nnexpr, undefined, type);
749769
// See comment above.
750770
this.emit('((');
751771
this.writeNode(nnexpr.expression);
752772
this.emit('))');
773+
if (this.templateSpanStackCount > 0) {
774+
this.emit(')');
775+
}
753776
return true;
754777
case ts.SyntaxKind.PropertyDeclaration:
755778
case ts.SyntaxKind.VariableStatement:

test_files/coerce/coerce.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ goog.module('test_files.coerce.coerce');var module = module || {id: 'test_files/
99
function acceptString(arg) { return arg; }
1010
acceptString(/** @type {?} */ (3));
1111
acceptString(/** @type {?} */ (3));
12+
acceptString(`${((3))}`);

test_files/coerce/coerce.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
function acceptString(arg: string): string { return arg; }
22
acceptString(<any>3);
3-
acceptString(3 as any);
3+
acceptString(3 as any);
4+
acceptString(`${3 as any}`);

test_files/coerce/coerce.tsickle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
*/
1111
function acceptString(arg: string): string { return arg; }
1212
acceptString( /** @type {?} */((<any>3)));
13-
acceptString( /** @type {?} */((3 as any)));
13+
acceptString( /** @type {?} */((3 as any)));
14+
acceptString(`${( /** @type {?} */((3 as any)))}`);

test_files/nullable/nullable.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ function NonPrimitives_tsickle_Closure_declarations() {
3737
function takesNonNullable(val) { }
3838
let /** @type {{field: (null|string|number)}} */ x = { field: null };
3939
takesNonNullable(/** @type {(string|number)} */ ((x.field)));
40+
takesNonNullable(`${(((x.field)))}`);
41+
let /** @type {?} */ ctx;
42+
takesNonNullable(`org/${(((ctx.getTargetOrganization()))).key}/admin/folders`);

test_files/nullable/nullable.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ function takesNonNullable(val: string|number) {}
2020

2121
let x: {field: string | null | number} = {field: null};
2222
takesNonNullable(x.field!);
23+
takesNonNullable(`${x.field!}`);
24+
let ctx: any;
25+
takesNonNullable(`org/${ctx.getTargetOrganization()!.key}/admin/folders`);

test_files/nullable/nullable.tsickle.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ function takesNonNullable(val: string|number) {}
5252

5353
let /** @type {{field: (null|string|number)}} */ x: {field: string | null | number} = {field: null};
5454
takesNonNullable( /** @type {(string|number)} */((x.field)));
55+
takesNonNullable(`${( /** @type {(string|number)} */((x.field)))}`);
56+
let /** @type {?} */ ctx: any;
57+
takesNonNullable(`org/${( /** @type {?} */((ctx.getTargetOrganization()))).key}/admin/folders`);

0 commit comments

Comments
 (0)