diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts
index d910128f6db86..89b673097b70c 100644
--- a/src/services/codefixes/importFixes.ts
+++ b/src/services/codefixes/importFixes.ts
@@ -663,13 +663,15 @@ namespace ts.codefix {
}
const { allowsImportingSpecifier } = createPackageJsonImportFilter(sourceFile, preferences, host);
return fixes.reduce((best, fix) =>
+ // Takes true branch of conditional if `fix` is better than `best`
compareModuleSpecifiers(fix, best, sourceFile, program, allowsImportingSpecifier) === Comparison.LessThan ? fix : best
);
}
+ /** @returns `Comparison.LessThan` if `a` is better than `b`. */
function compareModuleSpecifiers(a: ImportFix, b: ImportFix, importingFile: SourceFile, program: Program, allowsImportingSpecifier: (specifier: string) => boolean): Comparison {
if (a.kind !== ImportFixKind.UseNamespace && b.kind !== ImportFixKind.UseNamespace) {
- return compareBooleans(allowsImportingSpecifier(a.moduleSpecifier), allowsImportingSpecifier(b.moduleSpecifier))
+ return compareBooleans(allowsImportingSpecifier(b.moduleSpecifier), allowsImportingSpecifier(a.moduleSpecifier))
|| compareNodeCoreModuleSpecifiers(a.moduleSpecifier, b.moduleSpecifier, importingFile, program)
|| compareNumberOfDirectorySeparators(a.moduleSpecifier, b.moduleSpecifier);
}
diff --git a/tests/cases/fourslash/completionsImport_46332.ts b/tests/cases/fourslash/completionsImport_46332.ts
new file mode 100644
index 0000000000000..836faa5974784
--- /dev/null
+++ b/tests/cases/fourslash/completionsImport_46332.ts
@@ -0,0 +1,93 @@
+///
+
+// @module: esnext
+// @moduleResolution: node
+
+// @Filename: /node_modules/vue/package.json
+//// {
+//// "name": "vue",
+//// "types": "dist/vue.d.ts"
+//// }
+
+// @Filename: /node_modules/vue/dist/vue.d.ts
+//// export * from "@vue/runtime-dom"
+
+// @Filename: /node_modules/@vue/runtime-dom/package.json
+//// {
+//// "name": "@vue/runtime-dom",
+//// "types": "dist/runtime-dom.d.ts"
+//// }
+
+// @Filename: /node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
+//// export * from "@vue/runtime-core";
+//// export {}
+//// declare module '@vue/reactivity' {
+//// export interface RefUnwrapBailTypes {
+//// runtimeDOMBailTypes: any
+//// }
+//// }
+
+// @Filename: /node_modules/@vue/runtime-core/package.json
+//// {
+//// "name": "@vue/runtime-core",
+//// "types": "dist/runtime-core.d.ts"
+//// }
+
+// @Filename: /node_modules/@vue/runtime-core/dist/runtime-core.d.ts
+//// import { ref } from '@vue/reactivity';
+//// export { ref };
+//// declare module '@vue/reactivity' {
+//// export interface RefUnwrapBailTypes {
+//// runtimeCoreBailTypes: any
+//// }
+//// }
+
+// @Filename: /node_modules/@vue/reactivity/package.json
+//// {
+//// "name": "@vue/reactivity",
+//// "types": "dist/reactivity.d.ts"
+//// }
+
+// @Filename: /node_modules/@vue/reactivity/dist/reactivity.d.ts
+//// export declare function ref(): T;
+
+// @Filename: /package.json
+//// {
+//// "dependencies": {
+//// "vue": "*"
+//// }
+//// }
+
+// @Filename: /index.ts
+//// import {} from "vue";
+//// ref/**/
+
+verify.completions({
+ marker: "",
+ includes: [{
+ name: "ref",
+ source: "vue",
+ sourceDisplay: "vue",
+ hasAction: true,
+ sortText: completion.SortText.AutoImportSuggestions,
+ }],
+ preferences: {
+ includeCompletionsForModuleExports: true,
+ allowIncompleteCompletions: true,
+ },
+});
+
+verify.applyCodeActionFromCompletion("", {
+ name: "ref",
+ source: "vue",
+ description: `Add 'ref' to existing import declaration from "vue"`,
+ data: {
+ exportName: "ref",
+ fileName: "/node_modules/vue/dist/vue.d.ts",
+ },
+ preferences: {
+ includeCompletionsForModuleExports: true,
+ allowIncompleteCompletions: true,
+ },
+ newFileContent: `import { ref } from "vue";\nref`
+});