Merge pull request #23253 from Kingwl/definite-assignment-assertion-improve

improve parser and error message if definite assignment assertions in…
This commit is contained in:
Ryan Cavanaugh 2018-09-05 11:49:13 -07:00 committed by GitHub
commit 5d65e86756
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 100 additions and 3 deletions

View file

@ -29024,10 +29024,14 @@ namespace ts {
}
}
function checkGrammarForInvalidQuestionMark(questionToken: Node | undefined, message: DiagnosticMessage): boolean {
function checkGrammarForInvalidQuestionMark(questionToken: QuestionToken | undefined, message: DiagnosticMessage): boolean {
return !!questionToken && grammarErrorOnNode(questionToken, message);
}
function checkGrammarForInvalidExclamationToken(exclamationToken: ExclamationToken | undefined, message: DiagnosticMessage): boolean {
return !!exclamationToken && grammarErrorOnNode(exclamationToken, message);
}
function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) {
const enum Flags {
Property = 1,
@ -29072,8 +29076,10 @@ namespace ts {
// and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields
let currentKind: Flags;
switch (prop.kind) {
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
checkGrammarForInvalidExclamationToken(prop.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
/* tslint:disable:no-switch-case-fall-through */
case SyntaxKind.PropertyAssignment:
// Grammar checking for computedPropertyName and shorthandPropertyAssignment
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
if (name.kind === SyntaxKind.NumericLiteral) {
@ -29314,6 +29320,9 @@ namespace ts {
else if (checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) {
return true;
}
else if (checkGrammarForInvalidExclamationToken(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context)) {
return true;
}
else if (node.body === undefined) {
return grammarErrorAtPos(node, node.end - 1, ";".length, Diagnostics._0_expected, "{");
}

View file

@ -86,6 +86,7 @@ namespace ts {
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).name) ||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).exclamationToken) ||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
case SyntaxKind.SpreadAssignment:
@ -156,6 +157,7 @@ namespace ts {
visitNode(cbNode, (<FunctionLikeDeclaration>node).asteriskToken) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).name) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).questionToken) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).exclamationToken) ||
visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
@ -4713,8 +4715,10 @@ namespace ts {
const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
const tokenIsIdentifier = isIdentifier();
node.name = parsePropertyName();
// Disallowing of optional property assignments happens in the grammar checker.
// Disallowing of optional property assignments and definite assignment assertion happens in the grammar checker.
(<MethodDeclaration>node).questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
(<MethodDeclaration>node).exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken);
if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
return parseMethodDeclaration(<MethodDeclaration>node, asteriskToken);
}

View file

@ -883,6 +883,7 @@ namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
// used when ObjectLiteralExpression is used in ObjectAssignmentPattern
// it is grammar error to appear in actual object initializer
equalsToken?: Token<SyntaxKind.EqualsToken>;
@ -941,6 +942,7 @@ namespace ts {
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}

View file

@ -632,6 +632,7 @@ declare namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
@ -668,6 +669,7 @@ declare namespace ts {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction;

View file

@ -632,6 +632,7 @@ declare namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
@ -668,6 +669,7 @@ declare namespace ts {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction;

View file

@ -0,0 +1,15 @@
tests/cases/conformance/controlFlow/definiteAssignmentAssertionsWithObjectShortHand.ts(2,16): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertionsWithObjectShortHand.ts(5,7): error TS1162: An object member cannot be declared optional.
==== tests/cases/conformance/controlFlow/definiteAssignmentAssertionsWithObjectShortHand.ts (2 errors) ====
const a: string | undefined = 'ff';
const foo = { a! }
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
const bar = {
a ? () { }
~
!!! error TS1162: An object member cannot be declared optional.
}

View file

@ -0,0 +1,23 @@
//// [definiteAssignmentAssertionsWithObjectShortHand.ts]
const a: string | undefined = 'ff';
const foo = { a! }
const bar = {
a ? () { }
}
//// [definiteAssignmentAssertionsWithObjectShortHand.js]
"use strict";
var a = 'ff';
var foo = { a: a };
var bar = {
a: function () { }
};
//// [definiteAssignmentAssertionsWithObjectShortHand.d.ts]
declare const a: string | undefined;
declare const foo: {
a: string;
};
declare const bar: {};

View file

@ -0,0 +1,14 @@
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertionsWithObjectShortHand.ts ===
const a: string | undefined = 'ff';
>a : Symbol(a, Decl(definiteAssignmentAssertionsWithObjectShortHand.ts, 0, 5))
const foo = { a! }
>foo : Symbol(foo, Decl(definiteAssignmentAssertionsWithObjectShortHand.ts, 1, 5))
>a : Symbol(a, Decl(definiteAssignmentAssertionsWithObjectShortHand.ts, 1, 13))
const bar = {
>bar : Symbol(bar, Decl(definiteAssignmentAssertionsWithObjectShortHand.ts, 3, 5))
a ? () { }
>a : Symbol(a, Decl(definiteAssignmentAssertionsWithObjectShortHand.ts, 3, 13))
}

View file

@ -0,0 +1,17 @@
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertionsWithObjectShortHand.ts ===
const a: string | undefined = 'ff';
>a : string | undefined
>'ff' : "ff"
const foo = { a! }
>foo : { a: string; }
>{ a! } : { a: string; }
>a : string
const bar = {
>bar : {}
>{ a ? () { }} : {}
a ? () { }
>a : (() => void) | undefined
}

View file

@ -0,0 +1,9 @@
// @strict: true
// @declaration: true
const a: string | undefined = 'ff';
const foo = { a! }
const bar = {
a ? () { }
}