From dba042d7d5f544862a883f281dbe1911273ab47d Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 14 Sep 2020 19:12:33 -0700 Subject: [PATCH] Add quick fix to add 'void' to Promise resolved without value (#40558) * Add codefix to add 'void' to Promise resolved without value * Add specific error message in checker to reduce quick-fix time in editor --- src/compiler/checker.ts | 28 ++++++- src/compiler/diagnosticMessages.json | 12 +++ src/harness/fourslashImpl.ts | 24 ++++-- src/services/codefixes/fixAddVoidToPromise.ts | 82 +++++++++++++++++++ src/services/tsconfig.json | 1 + .../fourslash/codeFixAddVoidToPromise.1.ts | 14 ++++ .../fourslash/codeFixAddVoidToPromise.2.ts | 14 ++++ .../fourslash/codeFixAddVoidToPromise.3.ts | 14 ++++ .../fourslash/codeFixAddVoidToPromise.4.ts | 14 ++++ .../fourslash/codeFixAddVoidToPromise.5.ts | 9 ++ .../fourslash/codeFixAddVoidToPromiseJS.1.ts | 16 ++++ .../fourslash/codeFixAddVoidToPromiseJS.2.ts | 16 ++++ .../fourslash/codeFixAddVoidToPromiseJS.3.ts | 16 ++++ .../fourslash/codeFixAddVoidToPromiseJS.4.ts | 16 ++++ .../fourslash/codeFixAddVoidToPromiseJS.5.ts | 12 +++ .../codeFixAddVoidToPromiseJS_all.ts | 21 +++++ .../fourslash/codeFixAddVoidToPromise_all.ts | 19 +++++ ...aceComputedPropertyNameWellKnownSymbols.ts | 6 +- .../incrementalParsingDynamicImport1.ts | 4 +- .../incrementalParsingDynamicImport3.ts | 2 +- 20 files changed, 322 insertions(+), 18 deletions(-) create mode 100644 src/services/codefixes/fixAddVoidToPromise.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise.1.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise.2.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise.3.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise.4.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise.5.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS.1.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS.2.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS.3.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS.4.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS.5.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromiseJS_all.ts create mode 100644 tests/cases/fourslash/codeFixAddVoidToPromise_all.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf489dae320..81069b261ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26708,6 +26708,22 @@ namespace ts { } } + function isPromiseResolveArityError(node: CallLikeExpression) { + if (!isCallExpression(node) || !isIdentifier(node.expression)) return false; + + const symbol = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, undefined, undefined, false); + const decl = symbol?.valueDeclaration; + if (!decl || !isParameter(decl) || !isFunctionExpressionOrArrowFunction(decl.parent) || !isNewExpression(decl.parent.parent) || !isIdentifier(decl.parent.parent.expression)) { + return false; + } + + const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false); + if (!globalPromiseSymbol) return false; + + const constructorSymbol = getSymbolAtLocation(decl.parent.parent.expression, /*ignoreErrors*/ true); + return constructorSymbol === globalPromiseSymbol; + } + function getArgumentArityError(node: CallLikeExpression, signatures: readonly Signature[], args: readonly Expression[]) { let min = Number.POSITIVE_INFINITY; let max = Number.NEGATIVE_INFINITY; @@ -26740,9 +26756,15 @@ namespace ts { let spanArray: NodeArray; let related: DiagnosticWithLocation | undefined; - const error = hasRestParameter || hasSpreadArgument ? hasRestParameter && hasSpreadArgument ? Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more : - hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 : - Diagnostics.Expected_0_arguments_but_got_1_or_more : Diagnostics.Expected_0_arguments_but_got_1; + const error = hasRestParameter || hasSpreadArgument ? + hasRestParameter && hasSpreadArgument ? + Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more : + hasRestParameter ? + Diagnostics.Expected_at_least_0_arguments_but_got_1 : + Diagnostics.Expected_0_arguments_but_got_1_or_more : + paramRange === 1 && argCount === 0 && isPromiseResolveArityError(node) ? + Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise : + Diagnostics.Expected_0_arguments_but_got_1; if (closestSignature && getMinArgumentCount(closestSignature) > argCount && closestSignature.declaration) { const paramDecl = closestSignature.declaration.parameters[closestSignature.thisParameter ? argCount + 1 : argCount]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5a6a3213580..a46ddd430f9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3039,6 +3039,10 @@ "category": "Error", "code": 2793 }, + "Expected {0} arguments, but got {1}. Did you forget to include 'void' in your type argument to 'Promise'?": { + "category": "Error", + "code": 2794 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", @@ -5927,6 +5931,14 @@ "category": "Message", "code": 95142 }, + "Add 'void' to Promise resolved without a value": { + "category": "Message", + "code": 95143 + }, + "Add 'void' to all Promises resolved without a value": { + "category": "Message", + "code": 95144 + }, "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 f99eb118a06..299403d8974 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -339,17 +339,23 @@ namespace FourSlash { this.languageServiceAdapterHost.addScript(fileName, file, /*isRootFile*/ true); } }); - if (!compilationOptions.noLib) { - this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, - Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false); - compilationOptions.lib?.forEach(fileName => { + if (!compilationOptions.noLib) { + const seen = new Set(); + const addSourceFile = (fileName: string) => { + if (seen.has(fileName)) return; + seen.add(fileName); const libFile = Harness.Compiler.getDefaultLibrarySourceFile(fileName); ts.Debug.assertIsDefined(libFile, `Could not find lib file '${fileName}'`); - if (libFile) { - this.languageServiceAdapterHost.addScript(fileName, libFile.text, /*isRootFile*/ false); + this.languageServiceAdapterHost.addScript(fileName, libFile.text, /*isRootFile*/ false); + if (!ts.some(libFile.libReferenceDirectives)) return; + for (const directive of libFile.libReferenceDirectives) { + addSourceFile(`lib.${directive.fileName}.d.ts`); } - }); + }; + + addSourceFile(Harness.Compiler.defaultLibFileName); + compilationOptions.lib?.forEach(addSourceFile); } } @@ -3878,7 +3884,7 @@ namespace FourSlash { const testData = parseTestData(absoluteBasePath, content, absoluteFileName); const state = new TestState(absoluteFileName, absoluteBasePath, testType, testData); const actualFileName = Harness.IO.resolvePath(fileName) || absoluteFileName; - const output = ts.transpileModule(content, { reportDiagnostics: true, fileName: actualFileName, compilerOptions: { target: ts.ScriptTarget.ES2015, inlineSourceMap: true } }); + const output = ts.transpileModule(content, { reportDiagnostics: true, fileName: actualFileName, compilerOptions: { target: ts.ScriptTarget.ES2015, inlineSourceMap: true, inlineSources: true } }); if (output.diagnostics!.length > 0) { throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`); } @@ -3888,7 +3894,7 @@ namespace FourSlash { function runCode(code: string, state: TestState, fileName: string): void { // Compile and execute the test const generatedFile = ts.changeExtension(fileName, ".js"); - const wrappedCode = `(function(test, goTo, plugins, verify, edit, debug, format, cancellation, classification, completion, verifyOperationIsCancelled) {${code}\n//# sourceURL=${generatedFile}\n})`; + const wrappedCode = `(function(test, goTo, plugins, verify, edit, debug, format, cancellation, classification, completion, verifyOperationIsCancelled) {${code}\n//# sourceURL=${ts.getBaseFileName(generatedFile)}\n})`; type SourceMapSupportModule = typeof import("source-map-support") & { // TODO(rbuckton): This is missing from the DT definitions and needs to be added. diff --git a/src/services/codefixes/fixAddVoidToPromise.ts b/src/services/codefixes/fixAddVoidToPromise.ts new file mode 100644 index 00000000000..5e6add96dac --- /dev/null +++ b/src/services/codefixes/fixAddVoidToPromise.ts @@ -0,0 +1,82 @@ +/* @internal */ +namespace ts.codefix { + const fixName = "addVoidToPromise"; + const fixId = "addVoidToPromise"; + const errorCodes = [ + Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise.code + ]; + registerCodeFix({ + errorCodes, + fixIds: [fixId], + getCodeActions(context) { + const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span, context.program)); + if (changes.length > 0) { + return [createCodeFixAction(fixName, changes, Diagnostics.Add_void_to_Promise_resolved_without_a_value, fixId, Diagnostics.Add_void_to_all_Promises_resolved_without_a_value)]; + } + }, + getAllCodeActions(context: CodeFixAllContext) { + return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag, context.program, new Set())); + } + }); + + function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan, program: Program, seen?: Set) { + const node = getTokenAtPosition(sourceFile, span.start); + if (!isIdentifier(node) || !isCallExpression(node.parent) || node.parent.expression !== node || node.parent.arguments.length !== 0) return; + + const checker = program.getTypeChecker(); + const symbol = checker.getSymbolAtLocation(node); + + // decl should be `new Promise(() => {})` + const decl = symbol?.valueDeclaration; + if (!decl || !isParameter(decl) || !isNewExpression(decl.parent.parent)) return; + + // no need to make this change if we have already seen this parameter. + if (seen?.has(decl)) return; + seen?.add(decl); + + const typeArguments = getEffectiveTypeArguments(decl.parent.parent); + if (some(typeArguments)) { + // append ` | void` to type argument + const typeArgument = typeArguments[0]; + const needsParens = !isUnionTypeNode(typeArgument) && !isParenthesizedTypeNode(typeArgument) && + isParenthesizedTypeNode(factory.createUnionTypeNode([typeArgument, factory.createKeywordTypeNode(SyntaxKind.VoidKeyword)]).types[0]); + if (needsParens) { + changes.insertText(sourceFile, typeArgument.pos, "("); + } + changes.insertText(sourceFile, typeArgument.end, needsParens ? ") | void" : " | void"); + } + else { + // make sure the Promise is type is untyped (i.e., `unknown`) + const signature = checker.getResolvedSignature(node.parent); + const parameter = signature?.parameters[0]; + const parameterType = parameter && checker.getTypeOfSymbolAtLocation(parameter, decl.parent.parent); + if (isInJSFile(decl)) { + if (!parameterType || parameterType.flags & TypeFlags.AnyOrUnknown) { + // give the expression a type + changes.insertText(sourceFile, decl.parent.parent.end, `)`); + changes.insertText(sourceFile, skipTrivia(sourceFile.text, decl.parent.parent.pos), `/** @type {Promise} */(`); + } + } + else { + if (!parameterType || parameterType.flags & TypeFlags.Unknown) { + // add `void` type argument + changes.insertText(sourceFile, decl.parent.parent.expression.end, ""); + } + } + } + } + + function getEffectiveTypeArguments(node: NewExpression) { + if (isInJSFile(node)) { + if (isParenthesizedExpression(node.parent)) { + const jsDocType = getJSDocTypeTag(node.parent)?.typeExpression.type; + if (jsDocType && isTypeReferenceNode(jsDocType) && isIdentifier(jsDocType.typeName) && idText(jsDocType.typeName) === "Promise") { + return jsDocType.typeArguments; + } + } + } + else { + return node.typeArguments; + } + } +} \ No newline at end of file diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 8ec2432af65..dcd1020f284 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -107,6 +107,7 @@ "codefixes/splitTypeOnlyImport.ts", "codefixes/convertConstToLet.ts", "codefixes/fixExpectedComma.ts", + "codefixes/fixAddVoidToPromise.ts", "refactors/convertExport.ts", "refactors/convertImport.ts", "refactors/convertToOptionalChainExpression.ts", diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise.1.ts b/tests/cases/fourslash/codeFixAddVoidToPromise.1.ts new file mode 100644 index 00000000000..bd971cf49ff --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise.1.ts @@ -0,0 +1,14 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p1 = new Promise(resolve => resolve()); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 0, + newFileContent: `const p1 = new Promise(resolve => resolve());` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise.2.ts b/tests/cases/fourslash/codeFixAddVoidToPromise.2.ts new file mode 100644 index 00000000000..a60b52e1239 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise.2.ts @@ -0,0 +1,14 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p2 = new Promise(resolve => resolve()); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 0, + newFileContent: `const p2 = new Promise(resolve => resolve());` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise.3.ts b/tests/cases/fourslash/codeFixAddVoidToPromise.3.ts new file mode 100644 index 00000000000..0850491f18d --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise.3.ts @@ -0,0 +1,14 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p3 = new Promise(resolve => resolve()); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 0, + newFileContent: `const p3 = new Promise(resolve => resolve());` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise.4.ts b/tests/cases/fourslash/codeFixAddVoidToPromise.4.ts new file mode 100644 index 00000000000..b414cb4d1e7 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise.4.ts @@ -0,0 +1,14 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p4 = new Promise<{ x: number } & { y: string }>(resolve => resolve()); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 0, + newFileContent: `const p4 = new Promise<({ x: number } & { y: string }) | void>(resolve => resolve());` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise.5.ts b/tests/cases/fourslash/codeFixAddVoidToPromise.5.ts new file mode 100644 index 00000000000..d6854a71f41 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise.5.ts @@ -0,0 +1,9 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p4: Promise = new Promise(resolve => resolve()); + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS.1.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.1.ts new file mode 100644 index 00000000000..417506a510c --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.1.ts @@ -0,0 +1,16 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +////const p1 = new Promise(resolve => resolve()); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 2, + newFileContent: `const p1 = /** @type {Promise} */(new Promise(resolve => resolve()));` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS.2.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.2.ts new file mode 100644 index 00000000000..f3bdbb635fe --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.2.ts @@ -0,0 +1,16 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +////const p2 = /** @type {Promise} */(new Promise(resolve => resolve())); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 2, + newFileContent: `const p2 = /** @type {Promise} */(new Promise(resolve => resolve()));` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS.3.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.3.ts new file mode 100644 index 00000000000..92adfb610db --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.3.ts @@ -0,0 +1,16 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +////const p3 = /** @type {Promise} */(new Promise(resolve => resolve())); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 2, + newFileContent: `const p3 = /** @type {Promise} */(new Promise(resolve => resolve()));` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS.4.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.4.ts new file mode 100644 index 00000000000..171e1135d1a --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.4.ts @@ -0,0 +1,16 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +////const p4 = /** @type {Promise<{ x: number } & { y: string }>} */(new Promise(resolve => resolve())); + +verify.codeFix({ + errorCode: 2794, + description: "Add 'void' to Promise resolved without a value", + index: 2, + newFileContent: `const p4 = /** @type {Promise<({ x: number } & { y: string }) | void>} */(new Promise(resolve => resolve()));` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS.5.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.5.ts new file mode 100644 index 00000000000..fdb707a46c7 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS.5.ts @@ -0,0 +1,12 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +/////** @type {Promise} */ +////const p2 = new Promise(resolve => resolve()); + +verify.not.codeFixAvailable("Add 'void' to Promise resolved without a value"); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromiseJS_all.ts b/tests/cases/fourslash/codeFixAddVoidToPromiseJS_all.ts new file mode 100644 index 00000000000..5c37cd851d9 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromiseJS_all.ts @@ -0,0 +1,21 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true +// @allowJS: true +// @checkJS: true +// @filename: main.js +////const p1 = new Promise(resolve => resolve()); +////const p2 = /** @type {Promise} */(new Promise(resolve => resolve())); +////const p3 = /** @type {Promise} */(new Promise(resolve => resolve())); +////const p4 = /** @type {Promise<{ x: number } & { y: string }>} */(new Promise(resolve => resolve())); + +verify.codeFixAll({ + fixId: "addVoidToPromise", + fixAllDescription: ts.Diagnostics.Add_void_to_all_Promises_resolved_without_a_value.message, + newFileContent: `const p1 = /** @type {Promise} */(new Promise(resolve => resolve())); +const p2 = /** @type {Promise} */(new Promise(resolve => resolve())); +const p3 = /** @type {Promise} */(new Promise(resolve => resolve())); +const p4 = /** @type {Promise<({ x: number } & { y: string }) | void>} */(new Promise(resolve => resolve()));` +}); diff --git a/tests/cases/fourslash/codeFixAddVoidToPromise_all.ts b/tests/cases/fourslash/codeFixAddVoidToPromise_all.ts new file mode 100644 index 00000000000..6f31d3388f2 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddVoidToPromise_all.ts @@ -0,0 +1,19 @@ +/// + +// @target: esnext +// @lib: es2015 +// @strict: true + +////const p1 = new Promise(resolve => resolve()); +////const p2 = new Promise(resolve => resolve()); +////const p3 = new Promise(resolve => resolve()); +////const p4 = new Promise<{ x: number } & { y: string }>(resolve => resolve()); + +verify.codeFixAll({ + fixId: "addVoidToPromise", + fixAllDescription: ts.Diagnostics.Add_void_to_all_Promises_resolved_without_a_value.message, + newFileContent: `const p1 = new Promise(resolve => resolve()); +const p2 = new Promise(resolve => resolve()); +const p3 = new Promise(resolve => resolve()); +const p4 = new Promise<({ x: number } & { y: string }) | void>(resolve => resolve());` +}); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts index d87fcb73d4e..0fc8f3767d9 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceComputedPropertyNameWellKnownSymbols.ts @@ -47,7 +47,7 @@ class C implements I { throw new Error("Method not implemented."); } [Symbol.match]: boolean; - [Symbol.replace](...args: {}) { + [Symbol.replace](...args: any[]) { throw new Error("Method not implemented."); } [Symbol.search](str: string): number { @@ -56,7 +56,7 @@ class C implements I { [Symbol.species](): number { throw new Error("Method not implemented."); } - [Symbol.split](str: string, limit?: number): {} { + [Symbol.split](str: string, limit?: number): string[] { throw new Error("Method not implemented."); } [Symbol.toPrimitive](hint: "number"): number; @@ -65,7 +65,7 @@ class C implements I { [Symbol.toPrimitive](hint: any) { throw new Error("Method not implemented."); } - [Symbol.toStringTag]: string\; + [Symbol.toStringTag]: string; [Symbol.unscopables]: any; }`, }); diff --git a/tests/cases/fourslash/incrementalParsingDynamicImport1.ts b/tests/cases/fourslash/incrementalParsingDynamicImport1.ts index 511f3835f5b..557a05664fe 100644 --- a/tests/cases/fourslash/incrementalParsingDynamicImport1.ts +++ b/tests/cases/fourslash/incrementalParsingDynamicImport1.ts @@ -11,7 +11,7 @@ //// }) //// /*1*/ -verify.numberOfErrorsInCurrentFile(2); +verify.numberOfErrorsInCurrentFile(1); goTo.marker("1"); edit.insert(" "); -verify.numberOfErrorsInCurrentFile(2); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(1); \ No newline at end of file diff --git a/tests/cases/fourslash/incrementalParsingDynamicImport3.ts b/tests/cases/fourslash/incrementalParsingDynamicImport3.ts index 64aca403ad9..5279949f263 100644 --- a/tests/cases/fourslash/incrementalParsingDynamicImport3.ts +++ b/tests/cases/fourslash/incrementalParsingDynamicImport3.ts @@ -11,4 +11,4 @@ verify.numberOfErrorsInCurrentFile(0); goTo.marker("1"); edit.insert("("); -verify.numberOfErrorsInCurrentFile(3); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(1); \ No newline at end of file