Don’t filter when there’s no package.json, fix scoped package imports

This commit is contained in:
Andrew Branch committed 2019-07-29 10:21:31 -07:00
1 parent 52a0a00a16
commit 528f873b2d
6 files changed
+157 -23

No files matched your search

+34 -20
View File
@@ -571,37 +571,33 @@ namespace ts.codefix {
const packageJsons = findPackageJsons(getDirectoryPath(from.fileName), host);
const dependencyIterator = readPackageJsonDependencies();
forEachExternalModule(checker, allSourceFiles, (module, sourceFile) => {
if (sourceFile === undefined || sourceFile !== from && isImportablePath(from.fileName, sourceFile.fileName) && packageJsonAllowsImporting(sourceFile.fileName)) {
if (sourceFile === undefined) {
const maybeSourceFile = module.valueDeclaration.getSourceFile();
if (!maybeSourceFile || packageJsonAllowsImporting(maybeSourceFile.fileName)) {
cb(module);
}
}
else if (sourceFile && sourceFile !== from && isImportablePath(from.fileName, sourceFile.fileName) && packageJsonAllowsImporting(sourceFile.fileName)) {
cb(module);
}
});
let seenDeps: Map<true> | undefined;
function packageJsonAllowsImporting(fileName: string): Ternary {
const pathComponents = getPathComponents(getDirectoryPath(fileName));
const nodeModulesIndex = pathComponents.lastIndexOf("node_modules");
if (nodeModulesIndex === -1) {
return Ternary.Maybe;
}
const moduleSpecifier = pathComponents[nodeModulesIndex + 1] === "@types"
? pathComponents[nodeModulesIndex + 2]
: pathComponents[nodeModulesIndex + 1];
if (!moduleSpecifier) {
return Ternary.Maybe;
}
if (seenDeps && seenDeps.has(moduleSpecifier)) {
return Ternary.True;
function packageJsonAllowsImporting(fileName: string): boolean {
const moduleSpecifier = getModuleSpecifierFromFileName(fileName);
if (!moduleSpecifier || !packageJsons.length || seenDeps && seenDeps.has(moduleSpecifier)) {
return true;
}
let packageName: string;
while (packageName = dependencyIterator.next().value) {
(seenDeps || (seenDeps = createMap())).set(packageName, true);
if (packageName === moduleSpecifier) {
return Ternary.True;
const nameWithoutTypes = getPackageNameFromTypesPackageName(packageName);
(seenDeps || (seenDeps = createMap())).set(nameWithoutTypes, true);
if (nameWithoutTypes === moduleSpecifier) {
return true;
}
}
return Ternary.False;
return false;
}
type PackageJson = Record<string, Record<string, string> | undefined>;
@@ -620,6 +616,24 @@ namespace ts.codefix {
}
}
}
function getModuleSpecifierFromFileName(fileName: string): string | undefined {
const pathComponents = getPathComponents(getDirectoryPath(fileName));
const nodeModulesIndex = pathComponents.lastIndexOf("node_modules");
if (nodeModulesIndex === -1) {
return undefined;
}
const firstComponent = pathComponents[nodeModulesIndex + 1];
const moduleSpecifier = firstComponent &&
firstComponent === "@types" ? pathComponents[nodeModulesIndex + 2] :
startsWith(firstComponent, "@") ? `${firstComponent}/${pathComponents[nodeModulesIndex + 2]}` :
firstComponent;
if (!moduleSpecifier) {
return undefined;
}
return moduleSpecifier;
}
}
function forEachExternalModule(checker: TypeChecker, allSourceFiles: ReadonlyArray<SourceFile>, cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) {
@@ -14,7 +14,7 @@
//@Filename: /node_modules/@types/react/package.json
////{
//// "name": "react"
//// "name": "@types/react"
////}
//@Filename: /node_modules/@types/fake-react/index.d.ts
@@ -22,7 +22,7 @@
//@Filename: /node_modules/@types/fake-react/package.json
////{
//// "name": "fake-react"
//// "name": "@types/fake-react"
////}
//@Filename: /src/index.ts
@@ -0,0 +1,44 @@
/// <reference path="fourslash.ts" />
//@noEmit: true
//@Filename: /package.json
////{
//// "devDependencies": {
//// "@types/react": "*"
//// }
////}
//@Filename: /node_modules/@types/react/index.d.ts
////export declare var React: any;
//@Filename: /node_modules/@types/react/package.json
////{
//// "name": "@types/react"
////}
//@Filename: /node_modules/@types/fake-react/index.d.ts
////export declare var ReactFake: any;
//@Filename: /node_modules/@types/fake-react/package.json
////{
//// "name": "@types/fake-react"
////}
//@Filename: /src/index.ts
////const x = Re/**/
verify.completions({
marker: test.marker(""),
isNewIdentifierLocation: true,
includes: {
name: "React",
hasAction: true,
source: "/node_modules/@types/react/index",
sortText: completion.SortText.AutoImportSuggestions
},
excludes: "ReactFake",
preferences: {
includeCompletionsForModuleExports: true
}
});
@@ -0,0 +1,30 @@
/// <reference path="fourslash.ts" />
//@noEmit: true
//@Filename: /package.json
////{
//// "dependencies": {
//// }
////}
//@Filename: /node_modules/@types/node/timers.d.ts
////declare module "timers" {
//// function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timeout;
////}
//@Filename: /node_modules/@types/node/package.json
////{
//// "name": "@types/node",
////}
//@Filename: /src/index.ts
////setTimeo/**/
verify.completions({
marker: test.marker(""),
exact: completion.globals,
preferences: {
includeCompletionsForModuleExports: true
}
});
@@ -0,0 +1,46 @@
/// <reference path="fourslash.ts" />
//@noEmit: true
//@Filename: /package.json
////{
//// "dependencies": {
//// "react": "*"
//// }
////}
//@Filename: /node_modules/react/index.d.ts
////export declare var React: any;
//@Filename: /node_modules/react/package.json
////{
//// "name": "react",
//// "types": "./index.d.ts"
////}
//@Filename: /node_modules/fake-react/index.d.ts
////export declare var ReactFake: any;
//@Filename: /node_modules/fake-react/package.json
////{
//// "name": "fake-react",
//// "types": "./index.d.ts"
////}
//@Filename: /src/index.ts
////const x = Re/**/
verify.completions({
marker: test.marker(""),
isNewIdentifierLocation: true,
includes: {
name: "React",
hasAction: true,
source: "/node_modules/react/index",
sortText: completion.SortText.AutoImportSuggestions
},
excludes: "ReactFake",
preferences: {
includeCompletionsForModuleExports: true
}
});
@@ -3,7 +3,7 @@
//// [|f1/*0*/('');|]
// @Filename: package.json
//// { "dependencies": { "package-name": "latest" } }
//// { "dependencies": { "@scope/package-name": "latest" } }
// @Filename: node_modules/@scope/package-name/bin/lib/index.d.ts
//// export function f1(text: string): string;