From ad880627ce792583992d1d709e1a62ee649517dc Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 12 Apr 2022 21:21:52 +0300 Subject: [PATCH] fix(48653): throw an error on an invalid optional chain from new expression --- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/parser.ts | 3 +++ ...dOptionalChainFromNewExpression.errors.txt | 13 +++++++++++ .../invalidOptionalChainFromNewExpression.js | 19 ++++++++++++++++ ...alidOptionalChainFromNewExpression.symbols | 18 +++++++++++++++ ...nvalidOptionalChainFromNewExpression.types | 22 +++++++++++++++++++ .../invalidOptionalChainFromNewExpression.ts | 6 +++++ 7 files changed, 85 insertions(+) create mode 100644 tests/baselines/reference/invalidOptionalChainFromNewExpression.errors.txt create mode 100644 tests/baselines/reference/invalidOptionalChainFromNewExpression.js create mode 100644 tests/baselines/reference/invalidOptionalChainFromNewExpression.symbols create mode 100644 tests/baselines/reference/invalidOptionalChainFromNewExpression.types create mode 100644 tests/cases/compiler/invalidOptionalChainFromNewExpression.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e8a765e514cb5..2207f6c30d3ef 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -647,6 +647,10 @@ "category": "Error", "code": 1208 }, + "Invalid optional chain from new expression. Did you mean to call '{0}()'?": { + "category": "Error", + "code": 1209 + }, "Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of '{0}'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.": { "category": "Error", "code": 1210 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7642612e27a44..343d9d9d5adb2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5970,6 +5970,9 @@ namespace ts { typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; expression = (expression as ExpressionWithTypeArguments).expression; } + if (token() === SyntaxKind.QuestionDotToken) { + parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression)); + } const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; return finishNode(factory.createNewExpression(expression, typeArguments, argumentList), pos); } diff --git a/tests/baselines/reference/invalidOptionalChainFromNewExpression.errors.txt b/tests/baselines/reference/invalidOptionalChainFromNewExpression.errors.txt new file mode 100644 index 0000000000000..c9ecc87fdc0d1 --- /dev/null +++ b/tests/baselines/reference/invalidOptionalChainFromNewExpression.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/invalidOptionalChainFromNewExpression.ts(5,6): error TS1209: Invalid optional chain from new expression. Did you mean to call 'A()'? + + +==== tests/cases/compiler/invalidOptionalChainFromNewExpression.ts (1 errors) ==== + class A { + b() {} + } + + new A?.b() // error + ~~ +!!! error TS1209: Invalid optional chain from new expression. Did you mean to call 'A()'? + new A()?.b() // ok + \ No newline at end of file diff --git a/tests/baselines/reference/invalidOptionalChainFromNewExpression.js b/tests/baselines/reference/invalidOptionalChainFromNewExpression.js new file mode 100644 index 0000000000000..39a235554c71b --- /dev/null +++ b/tests/baselines/reference/invalidOptionalChainFromNewExpression.js @@ -0,0 +1,19 @@ +//// [invalidOptionalChainFromNewExpression.ts] +class A { + b() {} +} + +new A?.b() // error +new A()?.b() // ok + + +//// [invalidOptionalChainFromNewExpression.js] +var _a, _b; +var A = /** @class */ (function () { + function A() { + } + A.prototype.b = function () { }; + return A; +}()); +(_a = new A) === null || _a === void 0 ? void 0 : _a.b(); // error +(_b = new A()) === null || _b === void 0 ? void 0 : _b.b(); // ok diff --git a/tests/baselines/reference/invalidOptionalChainFromNewExpression.symbols b/tests/baselines/reference/invalidOptionalChainFromNewExpression.symbols new file mode 100644 index 0000000000000..b251cceab37af --- /dev/null +++ b/tests/baselines/reference/invalidOptionalChainFromNewExpression.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/invalidOptionalChainFromNewExpression.ts === +class A { +>A : Symbol(A, Decl(invalidOptionalChainFromNewExpression.ts, 0, 0)) + + b() {} +>b : Symbol(A.b, Decl(invalidOptionalChainFromNewExpression.ts, 0, 9)) +} + +new A?.b() // error +>new A?.b : Symbol(A.b, Decl(invalidOptionalChainFromNewExpression.ts, 0, 9)) +>A : Symbol(A, Decl(invalidOptionalChainFromNewExpression.ts, 0, 0)) +>b : Symbol(A.b, Decl(invalidOptionalChainFromNewExpression.ts, 0, 9)) + +new A()?.b() // ok +>new A()?.b : Symbol(A.b, Decl(invalidOptionalChainFromNewExpression.ts, 0, 9)) +>A : Symbol(A, Decl(invalidOptionalChainFromNewExpression.ts, 0, 0)) +>b : Symbol(A.b, Decl(invalidOptionalChainFromNewExpression.ts, 0, 9)) + diff --git a/tests/baselines/reference/invalidOptionalChainFromNewExpression.types b/tests/baselines/reference/invalidOptionalChainFromNewExpression.types new file mode 100644 index 0000000000000..abe2da883921c --- /dev/null +++ b/tests/baselines/reference/invalidOptionalChainFromNewExpression.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/invalidOptionalChainFromNewExpression.ts === +class A { +>A : A + + b() {} +>b : () => void +} + +new A?.b() // error +>new A?.b() : void +>new A?.b : () => void +>new A : A +>A : typeof A +>b : () => void + +new A()?.b() // ok +>new A()?.b() : void +>new A()?.b : () => void +>new A() : A +>A : typeof A +>b : () => void + diff --git a/tests/cases/compiler/invalidOptionalChainFromNewExpression.ts b/tests/cases/compiler/invalidOptionalChainFromNewExpression.ts new file mode 100644 index 0000000000000..e47512775e03e --- /dev/null +++ b/tests/cases/compiler/invalidOptionalChainFromNewExpression.ts @@ -0,0 +1,6 @@ +class A { + b() {} +} + +new A?.b() // error +new A()?.b() // ok