Bugs in missing import codefix
- We didn't locate the package.json correctly in cases where the module to be imported is in a subdirectory of the package - We didn't look at the types element in package.json (just typings) - We didn't remove /index.js from the path if the main module was in a subdirectory Fixes #16963
This commit is contained in:
parent
abb229e91b
commit
15d294d350
|
@ -504,42 +504,60 @@ namespace ts.codefix {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const indexOfNodeModules = moduleFileName.indexOf("node_modules");
|
||||
if (indexOfNodeModules < 0) {
|
||||
const indexOfTopNodeModules = moduleFileName.indexOf("node_modules");
|
||||
if (indexOfTopNodeModules < 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let relativeFileName: string;
|
||||
if (sourceDirectory.indexOf(moduleFileName.substring(0, indexOfNodeModules - 1)) === 0) {
|
||||
// if node_modules folder is in this folder or any of its parent folder, no need to keep it.
|
||||
relativeFileName = moduleFileName.substring(indexOfNodeModules + 13 /* "node_modules\".length */);
|
||||
}
|
||||
else {
|
||||
relativeFileName = getRelativePath(moduleFileName, sourceDirectory);
|
||||
}
|
||||
// Simplify the full file path to something that can be resolved by Node.
|
||||
// First remove the extension
|
||||
let moduleSpecifier = removeFileExtension(moduleFileName);
|
||||
// If the module could be imported by a directory name, use that directory's name
|
||||
moduleSpecifier = getDirectoryOrFileName(moduleSpecifier);
|
||||
// Get a path that's relative to node_modules or the importing file's path
|
||||
moduleSpecifier = getNodeResolvablePath(moduleSpecifier);
|
||||
// If the module was found in @types, get the actual node package name
|
||||
return getPackageNameFromAtTypesDirectory(moduleSpecifier);
|
||||
|
||||
relativeFileName = removeFileExtension(relativeFileName);
|
||||
if (endsWith(relativeFileName, "/index")) {
|
||||
relativeFileName = getDirectoryPath(relativeFileName);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
const moduleDirectory = getDirectoryPath(moduleFileName);
|
||||
const packageJsonContent = JSON.parse(context.host.readFile(combinePaths(moduleDirectory, "package.json")));
|
||||
function getDirectoryOrFileName(fullModulePathWithoutExtension: string): string {
|
||||
// If the file is the main module, it can be imported by the package name
|
||||
const indexOfLastNodeModules = moduleFileName.lastIndexOf("node_modules");
|
||||
const indexOfSlashAtPackageRoot = moduleFileName.indexOf("/", indexOfLastNodeModules + 13 /* "node_modules\".length */);
|
||||
const packageRootPath = moduleFileName.substring(0, indexOfSlashAtPackageRoot);
|
||||
const packageJsonPath = combinePaths(packageRootPath, "package.json");
|
||||
if (context.host.fileExists(packageJsonPath)) {
|
||||
const packageJsonContent = JSON.parse(context.host.readFile(packageJsonPath));
|
||||
if (packageJsonContent) {
|
||||
const mainFile = packageJsonContent.main || packageJsonContent.typings;
|
||||
if (mainFile) {
|
||||
const mainExportFile = toPath(mainFile, moduleDirectory, getCanonicalFileName);
|
||||
const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
|
||||
if (mainFileRelative) {
|
||||
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
|
||||
if (removeFileExtension(mainExportFile) === removeFileExtension(moduleFileName)) {
|
||||
relativeFileName = getDirectoryPath(relativeFileName);
|
||||
return packageRootPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
// If the file is index.js, it can be imported by its directory name
|
||||
if (endsWith(fullModulePathWithoutExtension, "/index")) {
|
||||
return getDirectoryPath(fullModulePathWithoutExtension);
|
||||
}
|
||||
|
||||
return fullModulePathWithoutExtension;
|
||||
}
|
||||
|
||||
return getPackageNameFromAtTypesDirectory(relativeFileName);
|
||||
function getNodeResolvablePath(path: string): string {
|
||||
const fullPathUptoNodeModules = moduleFileName.substring(0, indexOfTopNodeModules - 1);
|
||||
if (sourceDirectory.indexOf(fullPathUptoNodeModules) === 0) {
|
||||
const indexOfTopPackageName = indexOfTopNodeModules + 13 /* "node_modules\".length */;
|
||||
// if node_modules folder is in this folder or any of its parent folders, no need to keep it.
|
||||
const relativeToTopNodeModules = path.substring(indexOfTopPackageName);
|
||||
return relativeToTopNodeModules;
|
||||
}
|
||||
else {
|
||||
return getRelativePath(path, sourceDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// [|f1/*0*/('');|]
|
||||
|
||||
// @Filename: package.json
|
||||
//// { "dependencies": { "package-name": "latest" } }
|
||||
|
||||
// @Filename: node_modules/package-name/bin/lib/libfile.d.ts
|
||||
//// export function f1(text: string): string;
|
||||
|
||||
// @Filename: node_modules/package-name/bin/lib/libfile.js
|
||||
//// function f1(text) { }
|
||||
//// exports.f1 = f1;
|
||||
|
||||
// @Filename: node_modules/package-name/package.json
|
||||
//// {
|
||||
//// "main": "bin/lib/libfile.js",
|
||||
//// "types": "bin/lib/libfile.d.ts"
|
||||
//// }
|
||||
|
||||
verify.importFixAtPosition([
|
||||
`import { f1 } from "package-name";
|
||||
|
||||
f1('');`
|
||||
]);
|
|
@ -0,0 +1,25 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// [|f1/*0*/('');|]
|
||||
|
||||
// @Filename: package.json
|
||||
//// { "dependencies": { "package-name": "latest" } }
|
||||
|
||||
// @Filename: node_modules/package-name/node_modules/package-name2/bin/lib/libfile.d.ts
|
||||
//// export function f1(text: string): string;
|
||||
|
||||
// @Filename: node_modules/package-name/node_modules/package-name2/bin/lib/libfile.js
|
||||
//// function f1(text) { }
|
||||
//// exports.f1 = f1;
|
||||
|
||||
// @Filename: node_modules/package-name/node_modules/package-name2/package.json
|
||||
//// {
|
||||
//// "main": "bin/lib/libfile.js",
|
||||
//// "types": "bin/lib/libfile.d.ts"
|
||||
//// }
|
||||
|
||||
verify.importFixAtPosition([
|
||||
`import { f1 } from "package-name/node_modules/package-name2";
|
||||
|
||||
f1('');`
|
||||
]);
|
|
@ -0,0 +1,25 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// [|f1/*0*/('');|]
|
||||
|
||||
// @Filename: package.json
|
||||
//// { "dependencies": { "package-name": "latest" } }
|
||||
|
||||
// @Filename: node_modules/package-name/bin/lib/index.d.ts
|
||||
//// export function f1(text: string): string;
|
||||
|
||||
// @Filename: node_modules/package-name/bin/lib/index.js
|
||||
//// function f1(text) { }
|
||||
//// exports.f1 = f1;
|
||||
|
||||
// @Filename: node_modules/package-name/package.json
|
||||
//// {
|
||||
//// "main": "bin/lib/index.js",
|
||||
//// "types": "bin/lib/index.d.ts"
|
||||
//// }
|
||||
|
||||
verify.importFixAtPosition([
|
||||
`import { f1 } from "package-name";
|
||||
|
||||
f1('');`
|
||||
]);
|
Loading…
Reference in a new issue