From 813ddf7909fc55f0b41580a58d5e2349a2efec32 Mon Sep 17 00:00:00 2001 From: Zzzen <843968788@qq.com> Date: Thu, 1 Jul 2021 00:43:14 +0800 Subject: [PATCH] ensure export modifier is used before default modifier (#44570) * ensure export modifier is used before default modifier * gracefully handle `default function` * Revert "gracefully handle `default function`" This reverts commit 1d8e2887540f5abaa8b7192fee89ef8935be8640. * give better error message on default without leading export --- src/compiler/checker.ts | 3 +++ src/compiler/parser.ts | 5 ++++- .../classAbstractManyKeywords.errors.txt | 4 ++-- .../defaultKeywordWithoutExport1.errors.txt | 10 +++++++++ .../reference/defaultKeywordWithoutExport1.js | 21 +++++++++++++++++++ .../defaultKeywordWithoutExport1.symbols | 9 ++++++++ .../defaultKeywordWithoutExport1.types | 9 ++++++++ .../defaultKeywordWithoutExport2.errors.txt | 12 +++++++++++ .../reference/defaultKeywordWithoutExport2.js | 8 +++++++ .../defaultKeywordWithoutExport2.symbols | 5 +++++ .../defaultKeywordWithoutExport2.types | 5 +++++ .../compiler/defaultKeywordWithoutExport1.ts | 6 ++++++ .../compiler/defaultKeywordWithoutExport2.ts | 3 +++ 13 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport1.errors.txt create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport1.js create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport1.symbols create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport1.types create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport2.errors.txt create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport2.js create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport2.symbols create mode 100644 tests/baselines/reference/defaultKeywordWithoutExport2.types create mode 100644 tests/cases/compiler/defaultKeywordWithoutExport1.ts create mode 100644 tests/cases/compiler/defaultKeywordWithoutExport2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b1d2befee7e..bd576cecbfd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -41139,6 +41139,9 @@ namespace ts { if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { return grammarErrorOnNode(modifier, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); } + else if (!(flags & ModifierFlags.Export)) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "default"); + } flags |= ModifierFlags.Default; break; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f3ac472e122..bc7a23e26e4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2429,7 +2429,10 @@ namespace ts { function parsingContextErrors(context: ParsingContext) { switch (context) { - case ParsingContext.SourceElements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected); + case ParsingContext.SourceElements: + return token() === SyntaxKind.DefaultKeyword + ? parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ExportKeyword)) + : parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected); case ParsingContext.BlockStatements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected); case ParsingContext.SwitchClauses: return parseErrorAtCurrentToken(Diagnostics.case_or_default_expected); case ParsingContext.SwitchClauseStatements: return parseErrorAtCurrentToken(Diagnostics.Statement_expected); diff --git a/tests/baselines/reference/classAbstractManyKeywords.errors.txt b/tests/baselines/reference/classAbstractManyKeywords.errors.txt index 1b23bfac982..364b19186ab 100644 --- a/tests/baselines/reference/classAbstractManyKeywords.errors.txt +++ b/tests/baselines/reference/classAbstractManyKeywords.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractManyKeywords.ts(3,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractManyKeywords.ts(3,1): error TS1005: 'export' expected. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractManyKeywords.ts(4,17): error TS1005: '=' expected. @@ -7,7 +7,7 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst export abstract class B {} default abstract class C {} ~~~~~~~ -!!! error TS1128: Declaration or statement expected. +!!! error TS1005: 'export' expected. import abstract class D {} ~~~~~ !!! error TS1005: '=' expected. \ No newline at end of file diff --git a/tests/baselines/reference/defaultKeywordWithoutExport1.errors.txt b/tests/baselines/reference/defaultKeywordWithoutExport1.errors.txt new file mode 100644 index 00000000000..d970e7053d7 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport1.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/defaultKeywordWithoutExport1.ts(4,1): error TS1029: 'export' modifier must precede 'default' modifier. + + +==== tests/cases/compiler/defaultKeywordWithoutExport1.ts (1 errors) ==== + declare function decorator(constructor: any): any; + + @decorator + default class {} + ~~~~~~~ +!!! error TS1029: 'export' modifier must precede 'default' modifier. \ No newline at end of file diff --git a/tests/baselines/reference/defaultKeywordWithoutExport1.js b/tests/baselines/reference/defaultKeywordWithoutExport1.js new file mode 100644 index 00000000000..f9a93e262d1 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport1.js @@ -0,0 +1,21 @@ +//// [defaultKeywordWithoutExport1.ts] +declare function decorator(constructor: any): any; + +@decorator +default class {} + +//// [defaultKeywordWithoutExport1.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var default_1 = /** @class */ (function () { + function default_1() { + } + default_1 = __decorate([ + decorator + ], default_1); + return default_1; +}()); diff --git a/tests/baselines/reference/defaultKeywordWithoutExport1.symbols b/tests/baselines/reference/defaultKeywordWithoutExport1.symbols new file mode 100644 index 00000000000..b7318b2744a --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport1.symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/defaultKeywordWithoutExport1.ts === +declare function decorator(constructor: any): any; +>decorator : Symbol(decorator, Decl(defaultKeywordWithoutExport1.ts, 0, 0)) +>constructor : Symbol(constructor, Decl(defaultKeywordWithoutExport1.ts, 0, 27)) + +@decorator +>decorator : Symbol(decorator, Decl(defaultKeywordWithoutExport1.ts, 0, 0)) + +default class {} diff --git a/tests/baselines/reference/defaultKeywordWithoutExport1.types b/tests/baselines/reference/defaultKeywordWithoutExport1.types new file mode 100644 index 00000000000..c9866c9eb66 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport1.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/defaultKeywordWithoutExport1.ts === +declare function decorator(constructor: any): any; +>decorator : (constructor: any) => any +>constructor : any + +@decorator +>decorator : (constructor: any) => any + +default class {} diff --git a/tests/baselines/reference/defaultKeywordWithoutExport2.errors.txt b/tests/baselines/reference/defaultKeywordWithoutExport2.errors.txt new file mode 100644 index 00000000000..c5072379b30 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport2.errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/defaultKeywordWithoutExport2.ts(1,1): error TS1005: 'export' expected. +tests/cases/compiler/defaultKeywordWithoutExport2.ts(1,18): error TS1003: Identifier expected. + + +==== tests/cases/compiler/defaultKeywordWithoutExport2.ts (2 errors) ==== + default function () { + ~~~~~~~ +!!! error TS1005: 'export' expected. + ~ +!!! error TS1003: Identifier expected. + + } \ No newline at end of file diff --git a/tests/baselines/reference/defaultKeywordWithoutExport2.js b/tests/baselines/reference/defaultKeywordWithoutExport2.js new file mode 100644 index 00000000000..0f5dfe5d2a7 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport2.js @@ -0,0 +1,8 @@ +//// [defaultKeywordWithoutExport2.ts] +default function () { + +} + +//// [defaultKeywordWithoutExport2.js] +function () { +} diff --git a/tests/baselines/reference/defaultKeywordWithoutExport2.symbols b/tests/baselines/reference/defaultKeywordWithoutExport2.symbols new file mode 100644 index 00000000000..fb8a0ec6ce7 --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport2.symbols @@ -0,0 +1,5 @@ +=== tests/cases/compiler/defaultKeywordWithoutExport2.ts === +default function () { +> : Symbol((Missing), Decl(defaultKeywordWithoutExport2.ts, 0, 7)) + +} diff --git a/tests/baselines/reference/defaultKeywordWithoutExport2.types b/tests/baselines/reference/defaultKeywordWithoutExport2.types new file mode 100644 index 00000000000..3272127383e --- /dev/null +++ b/tests/baselines/reference/defaultKeywordWithoutExport2.types @@ -0,0 +1,5 @@ +=== tests/cases/compiler/defaultKeywordWithoutExport2.ts === +default function () { +> : () => void + +} diff --git a/tests/cases/compiler/defaultKeywordWithoutExport1.ts b/tests/cases/compiler/defaultKeywordWithoutExport1.ts new file mode 100644 index 00000000000..f80dbebe2e2 --- /dev/null +++ b/tests/cases/compiler/defaultKeywordWithoutExport1.ts @@ -0,0 +1,6 @@ +// @experimentaldecorators: true + +declare function decorator(constructor: any): any; + +@decorator +default class {} \ No newline at end of file diff --git a/tests/cases/compiler/defaultKeywordWithoutExport2.ts b/tests/cases/compiler/defaultKeywordWithoutExport2.ts new file mode 100644 index 00000000000..22e62b2a5ad --- /dev/null +++ b/tests/cases/compiler/defaultKeywordWithoutExport2.ts @@ -0,0 +1,3 @@ +default function () { + +} \ No newline at end of file