From 8a88c1c84ca410f09b4ad0dba5d8fc99e88d7ab3 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 13 Dec 2019 14:20:54 -0800 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20offer=20import=20fix=20for=20me?= =?UTF-8?q?mbers=20of=20arrays=20or=20classes=20(#35635)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Write failing test * Don’t offer import fix for members of arrays or classes --- src/compiler/checker.ts | 6 +++- src/harness/fourslashImpl.ts | 26 +++++++++++++-- src/harness/fourslashInterfaceImpl.ts | 4 +++ tests/cases/fourslash/fourslash.ts | 1 + ...meCodeFix_noDestructureNonObjectLiteral.ts | 32 +++++++++++++++++++ 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_noDestructureNonObjectLiteral.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a16ac458528..7e7235914f8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2878,7 +2878,11 @@ namespace ts { } const type = getTypeOfSymbol(exportEquals); - return type.flags & TypeFlags.Primitive ? undefined : getPropertyOfType(type, memberName); + return type.flags & TypeFlags.Primitive || + getObjectFlags(type) & ObjectFlags.Class || + isArrayOrTupleLikeType(type) + ? undefined + : getPropertyOfType(type, memberName); } function getExportsOfSymbol(symbol: Symbol): SymbolTable { diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index f413341dcc7..c0894d42804 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -2553,7 +2553,7 @@ namespace FourSlash { * Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found. * @param fileName Path to file where error should be retrieved from. */ - private getCodeFixes(fileName: string, errorCode?: number, preferences: ts.UserPreferences = ts.emptyOptions): readonly ts.CodeFixAction[] { + private getCodeFixes(fileName: string, errorCode?: number, preferences: ts.UserPreferences = ts.emptyOptions, position?: number): readonly ts.CodeFixAction[] { const diagnosticsForCodeFix = this.getDiagnostics(fileName, /*includeSuggestions*/ true).map(diagnostic => ({ start: diagnostic.start, length: diagnostic.length, @@ -2564,7 +2564,12 @@ namespace FourSlash { if (errorCode !== undefined && errorCode !== diagnostic.code) { return; } - + if (position !== undefined && diagnostic.start !== undefined && diagnostic.length !== undefined) { + const span = ts.createTextRangeFromSpan({ start: diagnostic.start, length: diagnostic.length }); + if (!ts.textRangeContainsPositionInclusive(span, position)) { + return; + } + } return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start!, diagnostic.start! + diagnostic.length!, [diagnostic.code], this.formatCodeSettings, preferences); }); } @@ -2614,6 +2619,23 @@ namespace FourSlash { }); } + public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[]) { + const marker = this.getMarkerByName(markerName); + const codeFixes = this.getCodeFixes(marker.fileName, ts.Diagnostics.Cannot_find_name_0.code, { + includeCompletionsForModuleExports: true, + includeCompletionsWithInsertText: true + }, marker.position).filter(f => f.fixId === ts.codefix.importFixId); + + const actualModuleSpecifiers = ts.mapDefined(codeFixes, fix => { + return ts.forEach(ts.flatMap(fix.changes, c => c.textChanges), c => { + const match = /(?:from |require\()(['"])((?:(?!\1).)*)\1/.exec(c.newText); + return match?.[2]; + }); + }); + + assert.deepEqual(actualModuleSpecifiers, moduleSpecifiers); + } + public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined) { const name = "verifyDocCommentTemplate"; const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 5e7ba4cd844..3ff3bef3006 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -434,6 +434,10 @@ namespace FourSlashInterface { this.state.verifyImportFixAtPosition(expectedTextArray, errorCode, preferences); } + public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[]) { + this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers); + } + public navigationBar(json: any, options?: { checkSpans?: boolean }) { this.state.verifyNavigationBar(json, options); } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 714883553cf..473962e64f1 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -330,6 +330,7 @@ declare namespace FourSlashInterface { fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: FormatCodeOptions): void; getAndApplyCodeFix(errorCode?: number, index?: number): void; importFixAtPosition(expectedTextArray: string[], errorCode?: number, options?: UserPreferences): void; + importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[]): void; navigationBar(json: any, options?: { checkSpans?: boolean }): void; navigationTree(json: any, options?: { checkSpans?: boolean }): void; diff --git a/tests/cases/fourslash/importNameCodeFix_noDestructureNonObjectLiteral.ts b/tests/cases/fourslash/importNameCodeFix_noDestructureNonObjectLiteral.ts new file mode 100644 index 00000000000..db1c899d70d --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_noDestructureNonObjectLiteral.ts @@ -0,0 +1,32 @@ +/// + +// @target: es2015 +// @strict: true +// @esModuleInterop: true + +// @Filename: /array.ts +////declare const arr: number[]; +////export = arr; + +// @Filename: /class-instance-member.ts +////class C { filter() {} } +////export = new C(); + +// @Filename: /object-literal.ts +////declare function filter(): void; +////export = { filter }; + +// @Filename: /jquery.d.ts +////interface JQueryStatic { +//// filter(): void; +////} +////declare const $: JQueryStatic; +////export = $; + +// @Filename: /jquery.js +////module.exports = {}; + +// @Filename: /index.ts +////filter/**/ + +verify.importFixModuleSpecifiers('', ['./object-literal', './jquery']);