Skip to content

Commit 4622718

Browse files
authored
Fix Issue #39155 (importModuleSpecifierEnding does not apply for module specifier completions) (#42467)
* Pass preferences down to getCompletionEntriesForRelativeModules * Add preferences to getExtensionsOptions call * Add test case * Fix test case typos
1 parent b7c0e5d commit 4622718

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

src/services/completions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ namespace ts.Completions {
701701

702702
const contextToken = findPrecedingToken(position, sourceFile);
703703
if (isInString(sourceFile, position, contextToken)) {
704-
return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken);
704+
return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken, preferences);
705705
}
706706

707707
// Compute all the completion symbols again.

src/services/stringCompletions.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace ts.Completions.StringCompletions {
77
}
88
if (isInString(sourceFile, position, contextToken)) {
99
if (!contextToken || !isStringLiteralLike(contextToken)) return undefined;
10-
const entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host);
10+
const entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host, preferences);
1111
return convertStringLiteralCompletions(entries, contextToken, sourceFile, checker, log, preferences);
1212
}
1313
}
@@ -52,9 +52,9 @@ namespace ts.Completions.StringCompletions {
5252
}
5353
}
5454

55-
export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, checker: TypeChecker, options: CompilerOptions, host: LanguageServiceHost, cancellationToken: CancellationToken) {
55+
export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, checker: TypeChecker, options: CompilerOptions, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences) {
5656
if (!contextToken || !isStringLiteralLike(contextToken)) return undefined;
57-
const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host);
57+
const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host, preferences);
5858
return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, checker, cancellationToken);
5959
}
6060

@@ -109,7 +109,7 @@ namespace ts.Completions.StringCompletions {
109109
readonly isNewIdentifier: boolean;
110110
}
111111
type StringLiteralCompletion = { readonly kind: StringLiteralCompletionKind.Paths, readonly paths: readonly PathCompletion[] } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes;
112-
function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost): StringLiteralCompletion | undefined {
112+
function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost, preferences: UserPreferences): StringLiteralCompletion | undefined {
113113
const parent = walkUpParentheses(node.parent);
114114
switch (parent.kind) {
115115
case SyntaxKind.LiteralType: {
@@ -136,7 +136,7 @@ namespace ts.Completions.StringCompletions {
136136
}
137137
return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType));
138138
case SyntaxKind.ImportType:
139-
return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
139+
return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) };
140140
case SyntaxKind.UnionType: {
141141
if (!isTypeReferenceNode(grandParent.parent)) {
142142
return undefined;
@@ -201,7 +201,7 @@ namespace ts.Completions.StringCompletions {
201201
// import x = require("/*completion position*/");
202202
// var y = require("/*completion position*/");
203203
// export * from "/*completion position*/";
204-
return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
204+
return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) };
205205

206206
default:
207207
return fromContextualType();
@@ -303,18 +303,18 @@ namespace ts.Completions.StringCompletions {
303303
Math.max(name.indexOf(directorySeparator), name.indexOf(altDirectorySeparator)) !== -1 ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span });
304304
}
305305

306-
function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): readonly PathCompletion[] {
307-
return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker));
306+
function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly PathCompletion[] {
307+
return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker, preferences));
308308
}
309309

310-
function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): readonly NameAndKind[] {
310+
function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly NameAndKind[] {
311311
const literalValue = normalizeSlashes(node.text);
312312

313313
const scriptPath = sourceFile.path;
314314
const scriptDirectory = getDirectoryPath(scriptPath);
315315

316316
return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (isRootedDiskPath(literalValue) || isUrl(literalValue))
317-
? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath)
317+
? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, preferences)
318318
: getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker);
319319
}
320320

@@ -325,8 +325,8 @@ namespace ts.Completions.StringCompletions {
325325
function getExtensionOptions(compilerOptions: CompilerOptions, includeExtensions = false): ExtensionOptions {
326326
return { extensions: getSupportedExtensionsForModuleResolution(compilerOptions), includeExtensions };
327327
}
328-
function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, scriptPath: Path) {
329-
const extensionOptions = getExtensionOptions(compilerOptions);
328+
function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, scriptPath: Path, preferences: UserPreferences) {
329+
const extensionOptions = getExtensionOptions(compilerOptions, preferences.importModuleSpecifierEnding === "js");
330330
if (compilerOptions.rootDirs) {
331331
return getCompletionEntriesForDirectoryFragmentWithRootDirs(
332332
compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/// <reference path='fourslash.ts'/>
2+
//@allowJs: true
3+
//@Filename:test.js
4+
////export function f(){
5+
//// return 1
6+
////}
7+
8+
//@Filename:module.js
9+
////import { f } from ".//**/"
10+
11+
12+
verify.completions({ marker: "", includes:{name:"test.js"}, preferences: {importModuleSpecifierEnding: "js" }, isNewIdentifierLocation: true})

0 commit comments

Comments
 (0)