Fix printing and emit for definite assignment assertions (#35095)

* Fix printing and emit for definite assignment assertions

* Make factories that handle definite assertions internal
This commit is contained in:
Wesley Wigham 2019-11-21 11:20:57 -08:00 committed by GitHub
parent a6d44aa52e
commit 614a07c7d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 42 additions and 3 deletions

View File

@ -3807,7 +3807,7 @@ namespace ts {
}
// Type annotations are TypeScript syntax.
if (node.type) {
if (node.type || node.exclamationToken) {
transformFlags |= TransformFlags.AssertTypeScript;
}

View File

@ -2741,6 +2741,7 @@ namespace ts {
function emitVariableDeclaration(node: VariableDeclaration) {
emit(node.name);
emit(node.exclamationToken);
emitTypeAnnotation(node.type);
emitInitializer(node.initializer, node.type ? node.type.end : node.name.end, node);
}

View File

@ -1937,6 +1937,7 @@ namespace ts {
}
export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression) {
/* Internally, one should probably use createTypeScriptVariableDeclaration instead and handle definite assignment assertions */
const node = <VariableDeclaration>createSynthesizedNode(SyntaxKind.VariableDeclaration);
node.name = asName(name);
node.type = type;
@ -1945,6 +1946,7 @@ namespace ts {
}
export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) {
/* Internally, one should probably use updateTypeScriptVariableDeclaration instead and handle definite assignment assertions */
return node.name !== name
|| node.type !== type
|| node.initializer !== initializer
@ -1952,6 +1954,26 @@ namespace ts {
: node;
}
/* @internal */
export function createTypeScriptVariableDeclaration(name: string | BindingName, exclaimationToken?: Token<SyntaxKind.ExclamationToken>, type?: TypeNode, initializer?: Expression) {
const node = <VariableDeclaration>createSynthesizedNode(SyntaxKind.VariableDeclaration);
node.name = asName(name);
node.type = type;
node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined;
node.exclamationToken = exclaimationToken;
return node;
}
/* @internal */
export function updateTypeScriptVariableDeclaration(node: VariableDeclaration, name: BindingName, exclaimationToken: Token<SyntaxKind.ExclamationToken> | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
return node.name !== name
|| node.type !== type
|| node.initializer !== initializer
|| node.exclamationToken !== exclaimationToken
? updateNode(createTypeScriptVariableDeclaration(name, exclaimationToken, type, initializer), node)
: node;
}
export function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) {
const node = <VariableDeclarationList>createSynthesizedNode(SyntaxKind.VariableDeclarationList);
node.flags |= flags & NodeFlags.BlockScoped;

View File

@ -937,7 +937,7 @@ namespace ts {
}
shouldEnterSuppressNewDiagnosticsContextContext = true;
suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types
return cleanup(updateVariableDeclaration(input, input.name, ensureType(input, input.type), ensureNoInitializer(input)));
return cleanup(updateTypeScriptVariableDeclaration(input, input.name, /*exclaimationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input)));
}
case SyntaxKind.TypeParameter: {
if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) {

View File

@ -2188,9 +2188,10 @@ namespace ts {
}
function visitVariableDeclaration(node: VariableDeclaration) {
return updateVariableDeclaration(
return updateTypeScriptVariableDeclaration(
node,
visitNode(node.name, visitor, isBindingName),
/*exclaimationToken*/ undefined,
/*type*/ undefined,
visitNode(node.initializer, visitor, isExpression));
}

View File

@ -67,6 +67,17 @@ namespace ts {
`class A extends B implements C implements D {}`,
ScriptTarget.ES2017
)));
// github #35093
printsCorrectly("definiteAssignmentAssertions", {}, printer => printer.printFile(createSourceFile(
"source.ts",
`class A {
prop!: string;
}
let x!: string;`,
ScriptTarget.ES2017
)));
});
describe("printBundle", () => {

View File

@ -0,0 +1,4 @@
class A {
prop!: string;
}
let x!: string;