diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 512e431fbe5ae..0150d5236bdef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26665,13 +26665,18 @@ namespace ts { if (!(node.flags & NodeFlags.AwaitContext)) { if (isTopLevelAwait(node)) { const sourceFile = getSourceFileOfNode(node); - if ((moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.System) || - languageVersion < ScriptTarget.ES2017 || - !isEffectiveExternalModule(sourceFile, compilerOptions)) { - if (!hasParseDiagnostics(sourceFile)) { - const span = getSpanOfTokenAtPosition(sourceFile, node.pos); + if (!hasParseDiagnostics(sourceFile)) { + let span: TextSpan | undefined; + if (!isEffectiveExternalModule(sourceFile, compilerOptions)) { + if (!span) span = getSpanOfTokenAtPosition(sourceFile, node.pos); + const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, + Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module); + diagnostics.add(diagnostic); + } + if ((moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.System) || languageVersion < ScriptTarget.ES2017) { + span = getSpanOfTokenAtPosition(sourceFile, node.pos); const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, - Diagnostics.await_outside_of_an_async_function_is_only_allowed_at_the_top_level_of_a_module_when_module_is_esnext_or_system_and_target_is_es2017_or_higher); + Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_esnext_or_system_and_the_target_option_is_set_to_es2017_or_higher); diagnostics.add(diagnostic); } } @@ -26681,7 +26686,7 @@ namespace ts { const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { const span = getSpanOfTokenAtPosition(sourceFile, node.pos); - const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.await_expression_is_only_allowed_within_an_async_function); + const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); const func = getContainingFunction(node); if (func && func.kind !== SyntaxKind.Constructor && (getFunctionFlags(func) & FunctionFlags.Async) === 0) { const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cd81020c0f1b7..8d31323a5d8c0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1269,6 +1269,11 @@ namespace ts { return result; } + /** + * Creates a new object by adding the own properties of `second`, then the own properties of `first`. + * + * NOTE: This means that if a property exists in both `first` and `second`, the property in `first` will be chosen. + */ export function extend(first: T1, second: T2): T1 & T2 { const result: T1 & T2 = {}; for (const id in second) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9ef1f69749b71..78e1a6d6a9545 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -863,7 +863,7 @@ "category": "Error", "code": 1300 }, - "'await' expression is only allowed within an async function.": { + "'await' expressions are only allowed within async functions and at the top levels of modules.": { "category": "Error", "code": 1308 }, @@ -1085,7 +1085,7 @@ }, "Split all invalid type-only imports": { "category": "Message", - "code": 1377 + "code": 1367 }, "Specify emit/checking behavior for imports that are only used for types": { "category": "Message", @@ -1115,10 +1115,14 @@ "category": "Message", "code": 1374 }, - "'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher.": { + "'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module.": { "category": "Error", "code": 1375 }, + "Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.": { + "category": "Error", + "code": 1376 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 @@ -5416,6 +5420,18 @@ "category": "Message", "code": 95096 }, + "Add 'export {}' to make this file into a module": { + "category": "Message", + "code": 95097 + }, + "Set the 'target' option in your configuration file to '{0}'": { + "category": "Message", + "code": 95098 + }, + "Set the 'module' option in your configuration file to '{0}'": { + "category": "Message", + "code": 95099 + }, "No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": { "category": "Error", diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index eb33a99d6f6ec..b3437e811b935 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -254,7 +254,7 @@ namespace FourSlash { const tsConfig = ts.convertCompilerOptionsFromJson(configJson.config.compilerOptions, baseDirectory, file.fileName); if (!tsConfig.errors || !tsConfig.errors.length) { - compilationOptions = ts.extend(compilationOptions, tsConfig.options); + compilationOptions = ts.extend(tsConfig.options, compilationOptions); } } configFileName = file.fileName; @@ -2574,6 +2574,10 @@ namespace FourSlash { if (typeof options.description === "string") { assert.equal(action.description, options.description); } + else if (Array.isArray(options.description)) { + const description = ts.formatStringFromArgs(options.description[0], options.description, 1); + assert.equal(action.description, description); + } else { assert.match(action.description, templateToRegExp(options.description.template)); } diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 04441468a7313..f3e3953ce3fbc 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1556,7 +1556,7 @@ namespace FourSlashInterface { } export interface VerifyCodeFixOptions extends NewContentOptions { - readonly description: string | DiagnosticIgnoredInterpolations; + readonly description: string | [string, ...(string | number)[]] | DiagnosticIgnoredInterpolations; readonly errorCode?: number; readonly index?: number; readonly preferences?: ts.UserPreferences; diff --git a/src/services/codefixes/addEmptyExportDeclaration.ts b/src/services/codefixes/addEmptyExportDeclaration.ts new file mode 100644 index 0000000000000..2b4c32cd11ab5 --- /dev/null +++ b/src/services/codefixes/addEmptyExportDeclaration.ts @@ -0,0 +1,20 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module.code], + getCodeActions: context => { + const { sourceFile } = context; + const changes = textChanges.ChangeTracker.with(context, changes => { + const exportDeclaration = createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createNamedExports([]), + /*moduleSpecifier*/ undefined, + /*isTypeOnly*/ false + ); + changes.insertNodeAtEndOfScope(sourceFile, sourceFile, exportDeclaration); + }); + return [createCodeFixActionWithoutFixAll("addEmptyExportDeclaration", changes, Diagnostics.Add_export_to_make_this_file_into_a_module)]; + }, + }); +} \ No newline at end of file diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 55dd4bd05567f..7f9cfd8731511 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -2,7 +2,7 @@ namespace ts.codefix { const fixId = "fixAwaitInSyncFunction"; const errorCodes = [ - Diagnostics.await_expression_is_only_allowed_within_an_async_function.code, + Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code, Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator.code, ]; registerCodeFix({ diff --git a/src/services/codefixes/fixModuleAndTargetOptions.ts b/src/services/codefixes/fixModuleAndTargetOptions.ts new file mode 100644 index 0000000000000..fe3eaebae9597 --- /dev/null +++ b/src/services/codefixes/fixModuleAndTargetOptions.ts @@ -0,0 +1,44 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_esnext_or_system_and_the_target_option_is_set_to_es2017_or_higher.code], + getCodeActions: context => { + const compilerOptions = context.program.getCompilerOptions(); + const { configFile } = compilerOptions; + if (configFile === undefined) { + return undefined; + } + + const codeFixes: CodeFixAction[] = []; + const moduleKind = getEmitModuleKind(compilerOptions); + const moduleOutOfRange = moduleKind >= ModuleKind.ES2015 && moduleKind < ModuleKind.ESNext; + if (moduleOutOfRange) { + const changes = textChanges.ChangeTracker.with(context, changes => { + setJsonCompilerOptionValue(changes, configFile, "module", createStringLiteral("esnext")); + }); + codeFixes.push(createCodeFixActionWithoutFixAll("fixModuleOption", changes, [Diagnostics.Set_the_module_option_in_your_configuration_file_to_0, "esnext"])); + } + + const target = getEmitScriptTarget(compilerOptions); + const targetOutOfRange = target < ScriptTarget.ES2017 || target > ScriptTarget.ESNext; + if (targetOutOfRange) { + const changes = textChanges.ChangeTracker.with(context, tracker => { + const configObject = getTsConfigObjectLiteralExpression(configFile); + if (!configObject) return; + + const options: [string, Expression][] = [["target", createStringLiteral("es2017")]]; + if (moduleKind === ModuleKind.CommonJS) { + // Ensure we preserve the default module kind (commonjs), as targets >= ES2015 have a default module kind of es2015. + options.push(["module", createStringLiteral("commonjs")]); + } + + setJsonCompilerOptionValues(tracker, configFile, options); + }); + + codeFixes.push(createCodeFixActionWithoutFixAll("fixTargetOption", changes, [Diagnostics.Set_the_target_option_in_your_configuration_file_to_0, "es2017"])); + } + + return codeFixes.length ? codeFixes : undefined; + } + }); +} diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 95fc499a2f9c6..930e703864f31 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -310,11 +310,10 @@ namespace ts.codefix { return undefined; } - export function setJsonCompilerOptionValue( + export function setJsonCompilerOptionValues( changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile, - optionName: string, - optionValue: Expression, + options: [string, Expression][] ) { const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); if (!tsconfigObjectLiteral) return undefined; @@ -323,9 +322,7 @@ namespace ts.codefix { if (compilerOptionsProperty === undefined) { changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment( "compilerOptions", - createObjectLiteral([ - createJsonPropertyAssignment(optionName, optionValue), - ]))); + createObjectLiteral(options.map(([optionName, optionValue]) => createJsonPropertyAssignment(optionName, optionValue)), /*multiLine*/ true))); return; } @@ -334,16 +331,26 @@ namespace ts.codefix { return; } - const optionProperty = findJsonProperty(compilerOptions, optionName); - - if (optionProperty === undefined) { - changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createJsonPropertyAssignment(optionName, optionValue)); - } - else { - changeTracker.replaceNode(configFile, optionProperty.initializer, optionValue); + for (const [optionName, optionValue] of options) { + const optionProperty = findJsonProperty(compilerOptions, optionName); + if (optionProperty === undefined) { + changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createJsonPropertyAssignment(optionName, optionValue)); + } + else { + changeTracker.replaceNode(configFile, optionProperty.initializer, optionValue); + } } } + export function setJsonCompilerOptionValue( + changeTracker: textChanges.ChangeTracker, + configFile: TsConfigSourceFile, + optionName: string, + optionValue: Expression, + ) { + setJsonCompilerOptionValues(changeTracker, configFile, [[optionName, optionValue]]); + } + export function createJsonPropertyAssignment(name: string, initializer: Expression) { return createPropertyAssignment(createStringLiteral(name), initializer); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 69cffe9b8f5f0..127b7ed1b0346 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -477,33 +477,69 @@ namespace ts.textChanges { public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void { this.insertNodeAtStartWorker(sourceFile, cls, newElement); } + public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void { this.insertNodeAtStartWorker(sourceFile, obj, newElement); } private insertNodeAtStartWorker(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, newElement: ClassElement | ObjectLiteralElementLike): void { - const clsStart = cls.getStart(sourceFile); - const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options) - + this.formatContext.options.indentSize!; - this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, { indentation, ...this.getInsertNodeAtStartPrefixSuffix(sourceFile, cls) }); - } - - private getInsertNodeAtStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): { prefix: string, suffix: string } { - const comma = isObjectLiteralExpression(cls) ? "," : ""; - if (getMembersOrProperties(cls).length === 0) { - if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) { - // For `class C {\n}`, don't add the trailing "\n" - const [open, close] = getClassOrObjectBraceEnds(cls, sourceFile); - const shouldSuffix = open && close && positionsAreOnSameLine(open, close, sourceFile); - return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") }; + const indentation = this.guessIndentationFromExistingMembers(sourceFile, cls) ?? this.computeIndentationForNewMember(sourceFile, cls); + this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, this.getInsertNodeAtStartInsertOptions(sourceFile, cls, indentation)); + } + + /** + * Tries to guess the indentation from the existing members of a class/interface/object. All members must be on + * new lines and must share the same indentation. + */ + private guessIndentationFromExistingMembers(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression) { + let indentation: number | undefined; + let lastRange: TextRange = cls; + for (const member of getMembersOrProperties(cls)) { + if (rangeStartPositionsAreOnSameLine(lastRange, member, sourceFile)) { + // each indented member must be on a new line + return undefined; } - else { - return { prefix: "", suffix: comma + this.newLineCharacter }; + const memberStart = member.getStart(sourceFile); + const memberIndentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options); + if (indentation === undefined) { + indentation = memberIndentation; } + else if (memberIndentation !== indentation) { + // indentation of multiple members is not consistent + return undefined; + } + lastRange = member; } - else { - return { prefix: this.newLineCharacter, suffix: comma }; - } + return indentation; + } + + private computeIndentationForNewMember(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression) { + const clsStart = cls.getStart(sourceFile); + return formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options) + + (this.formatContext.options.indentSize ?? 4); + } + + private getInsertNodeAtStartInsertOptions(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, indentation: number): InsertNodeOptions { + // Rules: + // - Always insert leading newline. + // - For object literals: + // - Add a trailing comma if there are existing members in the node, or the source file is not a JSON file + // (because trailing commas are generally illegal in a JSON file). + // - Add a leading comma if the source file is not a JSON file, there are existing insertions, + // and the node is empty (because we didn't add a trailing comma per the previous rule). + // - Only insert a trailing newline if body is single-line and there are no other insertions for the node. + // NOTE: This is handled in `finishClassesWithNodesInsertedAtStart`. + + const members = getMembersOrProperties(cls); + const isEmpty = members.length === 0; + const isFirstInsertion = addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile }); + const insertTrailingComma = isObjectLiteralExpression(cls) && (!isJsonSourceFile(sourceFile) || !isEmpty); + const insertLeadingComma = isObjectLiteralExpression(cls) && isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion; + return { + indentation, + prefix: (insertLeadingComma ? "," : "") + this.newLineCharacter, + suffix: insertTrailingComma ? "," : "" + }; } public insertNodeAfterComma(sourceFile: SourceFile, after: Node, newNode: Node): void { @@ -544,6 +580,7 @@ namespace ts.textChanges { prefix: after.end === sourceFile.end && isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") : options.prefix, }; } + private getInsertNodeAfterOptionsWorker(node: Node): InsertNodeOptions { switch (node.kind) { case SyntaxKind.ClassDeclaration: @@ -726,9 +763,16 @@ namespace ts.textChanges { private finishClassesWithNodesInsertedAtStart(): void { this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => { const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile); - // For `class C { }` remove the whitespace inside the braces. - if (openBraceEnd && closeBraceEnd && positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { - this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1)); + if (openBraceEnd !== undefined && closeBraceEnd !== undefined) { + const isEmpty = getMembersOrProperties(node).length === 0; + const isSingleLine = positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile); + if (isEmpty && isSingleLine && openBraceEnd !== closeBraceEnd - 1) { + // For `class C { }` remove the whitespace inside the braces. + this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1)); + } + if (isSingleLine) { + this.insertText(sourceFile, closeBraceEnd - 1, this.newLineCharacter); + } } }); } diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 946fe575d1823..47b525771eda3 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -47,6 +47,7 @@ "codeFixProvider.ts", "refactorProvider.ts", "codefixes/addConvertToUnknownForNonOverlappingTypes.ts", + "codefixes/addEmptyExportDeclaration.ts", "codefixes/addMissingAwait.ts", "codefixes/addMissingConst.ts", "codefixes/addMissingDeclareProperty.ts", @@ -70,6 +71,7 @@ "codefixes/fixConstructorForDerivedNeedSuperCall.ts", "codefixes/fixEnableExperimentalDecorators.ts", "codefixes/fixEnableJsxFlag.ts", + "codefixes/fixModuleAndTargetOptions.ts", "codefixes/fixExtendsInterfaceBecomesImplements.ts", "codefixes/fixForgottenThisPropertyAccess.ts", "codefixes/fixUnusedIdentifier.ts", diff --git a/tests/baselines/reference/awaitAndYield.errors.txt b/tests/baselines/reference/awaitAndYield.errors.txt index 54794fb01de8b..87842d35cc93f 100644 --- a/tests/baselines/reference/awaitAndYield.errors.txt +++ b/tests/baselines/reference/awaitAndYield.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/enums/awaitAndYield.ts(3,15): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/conformance/enums/awaitAndYield.ts(3,15): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/conformance/enums/awaitAndYield.ts(4,15): error TS1163: A 'yield' expression is only allowed in a generator body. @@ -7,7 +7,7 @@ tests/cases/conformance/enums/awaitAndYield.ts(4,15): error TS1163: A 'yield' ex enum E { foo = await x, ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. baz = yield 1, ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. diff --git a/tests/baselines/reference/awaitAndYieldInProperty.errors.txt b/tests/baselines/reference/awaitAndYieldInProperty.errors.txt index 0b6634dcc88d2..2aec2af52788f 100644 --- a/tests/baselines/reference/awaitAndYieldInProperty.errors.txt +++ b/tests/baselines/reference/awaitAndYieldInProperty.errors.txt @@ -1,15 +1,15 @@ tests/cases/conformance/classes/awaitAndYieldInProperty.ts(3,9): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. -tests/cases/conformance/classes/awaitAndYieldInProperty.ts(3,21): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/conformance/classes/awaitAndYieldInProperty.ts(3,21): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(4,16): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. -tests/cases/conformance/classes/awaitAndYieldInProperty.ts(4,28): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/conformance/classes/awaitAndYieldInProperty.ts(4,28): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(6,9): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(6,21): error TS1163: A 'yield' expression is only allowed in a generator body. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(7,16): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(7,28): error TS1163: A 'yield' expression is only allowed in a generator body. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(11,9): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. -tests/cases/conformance/classes/awaitAndYieldInProperty.ts(11,21): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/conformance/classes/awaitAndYieldInProperty.ts(11,21): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(12,16): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. -tests/cases/conformance/classes/awaitAndYieldInProperty.ts(12,28): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/conformance/classes/awaitAndYieldInProperty.ts(12,28): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(14,9): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(14,21): error TS1163: A 'yield' expression is only allowed in a generator body. tests/cases/conformance/classes/awaitAndYieldInProperty.ts(15,16): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. @@ -23,12 +23,12 @@ tests/cases/conformance/classes/awaitAndYieldInProperty.ts(15,28): error TS1163: ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. static [await x] = await x; ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. [yield 1] = yield 2; ~~~~~~~~~ @@ -47,12 +47,12 @@ tests/cases/conformance/classes/awaitAndYieldInProperty.ts(15,28): error TS1163: ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. static [await x] = await x; ~~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. [yield 1] = yield 2; ~~~~~~~~~ diff --git a/tests/baselines/reference/awaitInClassInAsyncFunction.errors.txt b/tests/baselines/reference/awaitInClassInAsyncFunction.errors.txt index 549fbd0b74866..53d4a48dd45af 100644 --- a/tests/baselines/reference/awaitInClassInAsyncFunction.errors.txt +++ b/tests/baselines/reference/awaitInClassInAsyncFunction.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/awaitInClassInAsyncFunction.ts(9,15): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInClassInAsyncFunction.ts(9,15): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. ==== tests/cases/compiler/awaitInClassInAsyncFunction.ts (1 errors) ==== @@ -12,7 +12,7 @@ tests/cases/compiler/awaitInClassInAsyncFunction.ts(9,15): error TS1308: 'await' return new class { baz = await bar(); ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. }; } \ No newline at end of file diff --git a/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt b/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt index aa07a57b57ce2..8224911c3c63d 100644 --- a/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt +++ b/tests/baselines/reference/awaitInNonAsyncFunction.errors.txt @@ -1,19 +1,19 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(4,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(5,10): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(5,10): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(9,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(10,10): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(10,10): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(14,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(15,3): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(15,3): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(19,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(20,10): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(20,10): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(24,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(25,9): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(25,9): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(30,9): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(31,5): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(31,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(34,7): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(35,5): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitInNonAsyncFunction.ts(35,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. tests/cases/compiler/awaitInNonAsyncFunction.ts(39,5): error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. -tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. ==== tests/cases/compiler/awaitInNonAsyncFunction.ts (16 errors) ==== @@ -26,7 +26,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:3:10: Did you mean to mark this function as 'async'? return await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:3:10: Did you mean to mark this function as 'async'? } @@ -37,7 +37,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:8:17: Did you mean to mark this function as 'async'? return await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:8:17: Did you mean to mark this function as 'async'? } @@ -48,7 +48,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:13:28: Did you mean to mark this function as 'async'? await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:13:28: Did you mean to mark this function as 'async'? } @@ -59,7 +59,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:18:19: Did you mean to mark this function as 'async'? return await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:18:19: Did you mean to mark this function as 'async'? }; @@ -70,7 +70,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:23:11: Did you mean to mark this function as 'async'? yield await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:23:11: Did you mean to mark this function as 'async'? } @@ -81,7 +81,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. } method(p: Promise) { for await (const _ of []); @@ -90,7 +90,7 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:33:3: Did you mean to mark this function as 'async'? await p; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitInNonAsyncFunction.ts:33:3: Did you mean to mark this function as 'async'? } } @@ -100,4 +100,4 @@ tests/cases/compiler/awaitInNonAsyncFunction.ts(40,1): error TS1375: 'await' out !!! error TS1103: A 'for-await-of' statement is only allowed within an async function or async generator. await null; ~~~~~ -!!! error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. \ No newline at end of file +!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. \ No newline at end of file diff --git a/tests/baselines/reference/awaitLiteralValues.errors.txt b/tests/baselines/reference/awaitLiteralValues.errors.txt index eb3237186e37f..b2e882eb44027 100644 --- a/tests/baselines/reference/awaitLiteralValues.errors.txt +++ b/tests/baselines/reference/awaitLiteralValues.errors.txt @@ -1,51 +1,51 @@ -tests/cases/compiler/awaitLiteralValues.ts(2,5): error TS1308: 'await' expression is only allowed within an async function. -tests/cases/compiler/awaitLiteralValues.ts(6,5): error TS1308: 'await' expression is only allowed within an async function. -tests/cases/compiler/awaitLiteralValues.ts(10,5): error TS1308: 'await' expression is only allowed within an async function. -tests/cases/compiler/awaitLiteralValues.ts(14,5): error TS1308: 'await' expression is only allowed within an async function. -tests/cases/compiler/awaitLiteralValues.ts(18,5): error TS1308: 'await' expression is only allowed within an async function. -tests/cases/compiler/awaitLiteralValues.ts(22,5): error TS1308: 'await' expression is only allowed within an async function. +tests/cases/compiler/awaitLiteralValues.ts(2,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. +tests/cases/compiler/awaitLiteralValues.ts(6,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. +tests/cases/compiler/awaitLiteralValues.ts(10,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. +tests/cases/compiler/awaitLiteralValues.ts(14,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. +tests/cases/compiler/awaitLiteralValues.ts(18,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. +tests/cases/compiler/awaitLiteralValues.ts(22,5): error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. ==== tests/cases/compiler/awaitLiteralValues.ts (6 errors) ==== function awaitString() { await 'literal'; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:1:10: Did you mean to mark this function as 'async'? } function awaitNumber() { await 1; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:5:10: Did you mean to mark this function as 'async'? } function awaitTrue() { await true; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:9:10: Did you mean to mark this function as 'async'? } function awaitFalse() { await false; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:13:10: Did you mean to mark this function as 'async'? } function awaitNull() { await null; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:17:10: Did you mean to mark this function as 'async'? } function awaitUndefined() { await undefined; ~~~~~ -!!! error TS1308: 'await' expression is only allowed within an async function. +!!! error TS1308: 'await' expressions are only allowed within async functions and at the top levels of modules. !!! related TS1356 tests/cases/compiler/awaitLiteralValues.ts:21:10: Did you mean to mark this function as 'async'? } \ No newline at end of file diff --git a/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt b/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt index 0bd384b85206d..10de2df71c67a 100644 --- a/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt +++ b/tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. ==== tests/cases/conformance/externalModules/topLevelAwait.ts (1 errors) ==== export const x = 1; await x; ~~~~~ -!!! error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. \ No newline at end of file diff --git a/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt b/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt index 0bd384b85206d..10de2df71c67a 100644 --- a/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt +++ b/tests/baselines/reference/topLevelAwait(module=system,target=es2015).errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. ==== tests/cases/conformance/externalModules/topLevelAwait.ts (1 errors) ==== export const x = 1; await x; ~~~~~ -!!! error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +!!! error TS1376: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher. \ No newline at end of file diff --git a/tests/baselines/reference/topLevelAwaitNonModule.errors.txt b/tests/baselines/reference/topLevelAwaitNonModule.errors.txt index 888c565e7a9d5..4cfb7239b9224 100644 --- a/tests/baselines/reference/topLevelAwaitNonModule.errors.txt +++ b/tests/baselines/reference/topLevelAwaitNonModule.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/externalModules/topLevelAwaitNonModule.ts(1,1): error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +tests/cases/conformance/externalModules/topLevelAwaitNonModule.ts(1,1): error TS1375: 'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module. tests/cases/conformance/externalModules/topLevelAwaitNonModule.ts(1,7): error TS2304: Cannot find name 'x'. ==== tests/cases/conformance/externalModules/topLevelAwaitNonModule.ts (2 errors) ==== await x; ~~~~~ -!!! error TS1375: 'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher. +!!! error TS1375: 'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module. ~ !!! error TS2304: Cannot find name 'x'. \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts b/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts index 1ce5c771ed40b..38d0d92e673c7 100644 --- a/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts +++ b/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts @@ -2,4 +2,4 @@ ////await a -verify.not.codeFixAvailable(); +verify.not.codeFixAvailable("addMissingAwait"); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceEmptyMultilineBody.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceEmptyMultilineBody.ts new file mode 100644 index 0000000000000..f0a98ececa89e --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceEmptyMultilineBody.ts @@ -0,0 +1,23 @@ +/// + +// @lib: es2017 + +////interface I { +//// x: number; +//// y: number; +////} +////class C implements I { +////} + +verify.codeFix({ + description: "Implement interface 'I'", + newFileContent: +`interface I { + x: number; + y: number; +} +class C implements I { + x: number; + y: number; +}`, +}); diff --git a/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsJsConfig.ts b/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsJsConfig.ts index 9d3c14f45bbbd..6681c2e814652 100644 --- a/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsJsConfig.ts +++ b/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsJsConfig.ts @@ -16,7 +16,7 @@ verify.codeFix({ "/dir/jsconfig.json": `{ "compilerOptions": { - "jsx": "react", + "jsx": "react" } }`, }, diff --git a/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsTsConfig.ts b/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsTsConfig.ts index 7b314feeecd50..0234610090edf 100644 --- a/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsTsConfig.ts +++ b/tests/cases/fourslash/codeFixEnableJsxFlag_blankCompilerOptionsTsConfig.ts @@ -16,7 +16,7 @@ verify.codeFix({ "/dir/tsconfig.json": `{ "compilerOptions": { - "jsx": "react", + "jsx": "react" } }`, }, diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_blankCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_blankCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..deced910eb658 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_blankCompilerOptionsInTsConfig.ts @@ -0,0 +1,14 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// } +////} + + +// Cannot fix module when default module option is `commonjs`... +verify.not.codeFixAvailable("fixModuleOption"); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_compatibleCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_compatibleCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..dd592d1c3eb24 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_compatibleCompilerOptionsInTsConfig.ts @@ -0,0 +1,15 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "target": "es2017", +//// "module": "esnext" +//// } +////} + + +verify.not.codeFixAvailable("fixModuleOption"); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_existingCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_existingCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..7dd5101341ee3 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_existingCompilerOptionsInTsConfig.ts @@ -0,0 +1,25 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "module": "es2015" +//// } +////} + + +verify.codeFix({ + description: [ts.Diagnostics.Set_the_module_option_in_your_configuration_file_to_0.message, "esnext"], + index: 0, + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "module": "esnext" + } +}` + } +}); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_missingCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_missingCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..8c84776ae47c2 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_missingCompilerOptionsInTsConfig.ts @@ -0,0 +1,11 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +////} + +// cannot fix module when default options are applied +verify.not.codeFixAvailable("fixModuleOption"); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_noTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_noTsConfig.ts new file mode 100644 index 0000000000000..906fda09298ea --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_noTsConfig.ts @@ -0,0 +1,8 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; + + +verify.not.codeFixAvailable("fixModuleOption"); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_module_targetES2017CompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_module_targetES2017CompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..3857ab2ddefe9 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_module_targetES2017CompilerOptionsInTsConfig.ts @@ -0,0 +1,28 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "target": "es2017" +//// } +////} + +verify.not.codeFixAvailable("fixTargetOption"); +verify.codeFixAvailable("fixModuleOption"); + +// verify.codeFix({ +// description: [ts.Diagnostics.Set_the_module_option_in_your_configuration_file_to_0.message, "esnext"], +// index: 0, +// newFileContent: { +// "/dir/tsconfig.json": +// `{ +// "compilerOptions": { +// "target": "es2017", +// "module": "esnext", +// } +// }` +// } +// }); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_notAModule.ts b/tests/cases/fourslash/codeFixTopLevelAwait_notAModule.ts new file mode 100644 index 0000000000000..453571cb87592 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_notAModule.ts @@ -0,0 +1,21 @@ +/// +////declare const p: Promise; +////await p; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "target": "esnext", +//// "module": "esnext" +//// } +////} + +verify.codeFix({ + description: ts.Diagnostics.Add_export_to_make_this_file_into_a_module.message, + index: 0, + newFileContent: + `declare const p: Promise; +await p; + +export { }; +` +}); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_target_blankCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_target_blankCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..1c647bfc12ae1 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_target_blankCompilerOptionsInTsConfig.ts @@ -0,0 +1,25 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// } +////} + + +verify.codeFix({ + description: [ts.Diagnostics.Set_the_target_option_in_your_configuration_file_to_0.message, "es2017"], + index: 0, + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs" + } +}` + } +}); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_target_compatibleCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_target_compatibleCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..7236dea342c27 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_target_compatibleCompilerOptionsInTsConfig.ts @@ -0,0 +1,15 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "target": "es2017", +//// "module": "esnext" +//// } +////} + + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_target_existingCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_target_existingCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..c50aa0d5728dc --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_target_existingCompilerOptionsInTsConfig.ts @@ -0,0 +1,25 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "target": "es2015" +//// } +////} + + +verify.codeFix({ + description: [ts.Diagnostics.Set_the_target_option_in_your_configuration_file_to_0.message, "es2017"], + index: 1, + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "target": "es2017" + } +}` + } +}); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_target_missingCompilerOptionsInTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_target_missingCompilerOptionsInTsConfig.ts new file mode 100644 index 0000000000000..65102909524ac --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_target_missingCompilerOptionsInTsConfig.ts @@ -0,0 +1,23 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; +// @filename: /dir/tsconfig.json +////{ +////} + + +verify.codeFix({ + description: [ts.Diagnostics.Set_the_target_option_in_your_configuration_file_to_0.message, "es2017"], + index: 0, + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs" + } +}` + } +}); diff --git a/tests/cases/fourslash/codeFixTopLevelAwait_target_noTsConfig.ts b/tests/cases/fourslash/codeFixTopLevelAwait_target_noTsConfig.ts new file mode 100644 index 0000000000000..0173b6f198236 --- /dev/null +++ b/tests/cases/fourslash/codeFixTopLevelAwait_target_noTsConfig.ts @@ -0,0 +1,8 @@ +/// +// @filename: /dir/a.ts +////declare const p: Promise; +////await p; +////export {}; + + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts index f8dcbf75e4824..0f52d496b700a 100644 --- a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts @@ -19,7 +19,7 @@ verify.codeFix({ "/dir/jsconfig.json": `{ "compilerOptions": { - "experimentalDecorators": true, + "experimentalDecorators": true } }`, }, diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts index 0e19b42d92133..48bc32e58213c 100644 --- a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts @@ -19,7 +19,7 @@ verify.codeFix({ "/dir/tsconfig.json": `{ "compilerOptions": { - "experimentalDecorators": true, + "experimentalDecorators": true } }`, }, diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts index 644fce3a35f56..d3370433b6a6a 100644 --- a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts @@ -16,7 +16,9 @@ verify.codeFix({ newFileContent: { "/dir/jsconfig.json": `{ - "compilerOptions": { "experimentalDecorators": true }, + "compilerOptions": { + "experimentalDecorators": true + } }`, }, }); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts index 6d7006f3ce1ac..de51cafee224e 100644 --- a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts @@ -16,7 +16,9 @@ verify.codeFix({ newFileContent: { "/dir/tsconfig.json": `{ - "compilerOptions": { "experimentalDecorators": true }, + "compilerOptions": { + "experimentalDecorators": true + } }`, }, }); diff --git a/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInJsconfig.ts index 89769c49d0b9b..4a041b67a1f38 100644 --- a/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInJsconfig.ts +++ b/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInJsconfig.ts @@ -13,7 +13,9 @@ verify.codeFix({ newFileContent: { "/dir/jsconfig.json": `{ - "compilerOptions": { "jsx": "react" }, + "compilerOptions": { + "jsx": "react" + } }`, }, }); diff --git a/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInTsconfig.ts b/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInTsconfig.ts index dc81c7970af27..f41bd8bc210de 100644 --- a/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInTsconfig.ts +++ b/tests/cases/fourslash/codefixEnableJsxFlag_missingCompilerOptionsInTsconfig.ts @@ -13,7 +13,9 @@ verify.codeFix({ newFileContent: { "/dir/tsconfig.json": `{ - "compilerOptions": { "jsx": "react" }, + "compilerOptions": { + "jsx": "react" + } }`, }, }); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index baeff000912b8..692e47a1421da 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -226,7 +226,7 @@ declare namespace FourSlashInterface { jsxClosingTag(map: { [markerName: string]: { readonly newText: string } | undefined }): void; isInCommentAtPosition(onlyMultiLineDiverges?: boolean): void; codeFix(options: { - description: string | DiagnosticIgnoredInterpolations, + description: string | [string, ...(string | number)[]] | DiagnosticIgnoredInterpolations, newFileContent?: NewFileContent, newRangeContent?: string, errorCode?: number,