Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2877,7 +2877,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 {
Expand Down
26 changes: 24 additions & 2 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
});
}
Expand Down Expand Up @@ -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)!;
Expand Down
6 changes: 5 additions & 1 deletion src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -1602,4 +1606,4 @@ namespace FourSlashInterface {
readonly providePrefixAndSuffixTextForRename?: boolean;
};
export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string };
}
}
1 change: 1 addition & 0 deletions tests/cases/fourslash/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// <reference path="fourslash.ts" />

// @target: es2015
// @strict: true
// @esModuleInterop: true

// @Filename: /array.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silly question: you don't need the leading /, do you? I never use it but see tests that do, and I have no idea what the difference is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without leading / the array.ts's full path will be /tests/cases/compiler I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No you don’t, but leaving it off scares me because I don’t understand what assumptions are being made about the file system and it makes me uncomfortable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just imagining writing real files to / and that scared me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macOS root is no longer user-writable so the test would have failed for me 😁

////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']);