From a027cfa8acbfea3eb3753ef32435f77d3f0a0a23 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 13 Apr 2022 06:16:43 -0700 Subject: [PATCH] More permissive parsing of instantiation expressions (#48659) * More permissive parsing of expressions with type arguments * Add test --- src/compiler/parser.ts | 28 ++----------------- .../instantiationExpressionErrors.errors.txt | 5 ++++ .../instantiationExpressionErrors.js | 12 ++++++++ .../instantiationExpressionErrors.symbols | 8 ++++++ .../instantiationExpressionErrors.types | 10 +++++++ .../instantiationExpressionErrors.ts | 5 ++++ 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 2a96a3b7cd3..247381f0251 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5735,34 +5735,10 @@ namespace ts { case SyntaxKind.OpenParenToken: // foo( case SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` case SyntaxKind.TemplateHead: // foo `...${100}...` - // These tokens can't follow in a call expression, nor can they start an - // expression. So, consider the type argument list part of an instantiation - // expression. - // falls through - case SyntaxKind.CommaToken: // foo, - case SyntaxKind.DotToken: // foo. - case SyntaxKind.QuestionDotToken: // foo?. - case SyntaxKind.CloseParenToken: // foo) - case SyntaxKind.CloseBracketToken: // foo] - case SyntaxKind.ColonToken: // foo: - case SyntaxKind.SemicolonToken: // foo; - case SyntaxKind.QuestionToken: // foo? - case SyntaxKind.EqualsEqualsToken: // foo == - case SyntaxKind.EqualsEqualsEqualsToken: // foo === - case SyntaxKind.ExclamationEqualsToken: // foo != - case SyntaxKind.ExclamationEqualsEqualsToken: // foo !== - case SyntaxKind.AmpersandAmpersandToken: // foo && - case SyntaxKind.BarBarToken: // foo || - case SyntaxKind.QuestionQuestionToken: // foo ?? - case SyntaxKind.CaretToken: // foo ^ - case SyntaxKind.AmpersandToken: // foo & - case SyntaxKind.BarToken: // foo | - case SyntaxKind.CloseBraceToken: // foo } - case SyntaxKind.EndOfFileToken: // foo return true; } - // Treat anything else as an expression. - return false; + // Consider something a type argument list only if the following token can't start an expression. + return !isStartOfExpression(); } function parsePrimaryExpression(): PrimaryExpression { diff --git a/tests/baselines/reference/instantiationExpressionErrors.errors.txt b/tests/baselines/reference/instantiationExpressionErrors.errors.txt index d0ded2ca917..5b60983d594 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.errors.txt +++ b/tests/baselines/reference/instantiationExpressionErrors.errors.txt @@ -72,4 +72,9 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpr const x3 = f; true; + + // Parsed as instantiation expression + + const x4 = f + if (true) {} \ No newline at end of file diff --git a/tests/baselines/reference/instantiationExpressionErrors.js b/tests/baselines/reference/instantiationExpressionErrors.js index c0c4d9b5b68..9f6b17f1378 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.js +++ b/tests/baselines/reference/instantiationExpressionErrors.js @@ -40,6 +40,11 @@ true; const x3 = f; true; + +// Parsed as instantiation expression + +const x4 = f +if (true) {} //// [instantiationExpressionErrors.js] @@ -70,6 +75,9 @@ var x2 = f < true > // Parsed as instantiation expression var x3 = (f); true; +// Parsed as instantiation expression +var x4 = (f); +if (true) { } //// [instantiationExpressionErrors.d.ts] @@ -101,3 +109,7 @@ declare const x3: { (): true; g(): U; }; +declare const x4: { + (): true; + g(): U; +}; diff --git a/tests/baselines/reference/instantiationExpressionErrors.symbols b/tests/baselines/reference/instantiationExpressionErrors.symbols index a9e99be8987..dc1e6d5d64b 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.symbols +++ b/tests/baselines/reference/instantiationExpressionErrors.symbols @@ -99,3 +99,11 @@ const x3 = f; true; +// Parsed as instantiation expression + +const x4 = f +>x4 : Symbol(x4, Decl(instantiationExpressionErrors.ts, 44, 5)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +if (true) {} + diff --git a/tests/baselines/reference/instantiationExpressionErrors.types b/tests/baselines/reference/instantiationExpressionErrors.types index 3886d802526..334cb69865e 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.types +++ b/tests/baselines/reference/instantiationExpressionErrors.types @@ -122,3 +122,13 @@ const x3 = f; true; >true : true +// Parsed as instantiation expression + +const x4 = f +>x4 : { (): true; g(): U; } +>f : { (): T; g(): U; } +>true : true + +if (true) {} +>true : true + diff --git a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts index c34a12f13bb..1a9377ae9c5 100644 --- a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts +++ b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts @@ -42,3 +42,8 @@ true; const x3 = f; true; + +// Parsed as instantiation expression + +const x4 = f +if (true) {}