Limit auto import provider project size (#39855)

* Limit auto import provider project size

* Add test

* Make option configurable

* Fix test

* Only bail when setting is auto

* Fix other test

* Update API baseline
This commit is contained in:
Andrew Branch 2020-08-02 17:47:49 -07:00 committed by GitHub
parent 94989789df
commit 86a87c493c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 44 additions and 20 deletions

View File

@ -8058,7 +8058,7 @@ namespace ts {
readonly importModuleSpecifierEnding?: "auto" | "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly includePackageJsonAutoImports?: "exclude-dev" | "all" | "none";
readonly includePackageJsonAutoImports?: "auto" | "on" | "off";
readonly provideRefactorNotApplicableReason?: boolean;
}

View File

@ -3825,9 +3825,9 @@ namespace ts.server {
/*@internal*/
includePackageJsonAutoImports(): PackageJsonAutoImportPreference {
switch (this.hostConfiguration.preferences.includePackageJsonAutoImports) {
case "none": return PackageJsonAutoImportPreference.None;
case "all": return PackageJsonAutoImportPreference.All;
default: return PackageJsonAutoImportPreference.ExcludeDevDependencies;
case "on": return PackageJsonAutoImportPreference.On;
case "off": return PackageJsonAutoImportPreference.Off;
default: return PackageJsonAutoImportPreference.Auto;
}
}

View File

@ -1631,11 +1631,11 @@ namespace ts.server {
/*@internal*/
includePackageJsonAutoImports(): PackageJsonAutoImportPreference {
if (this.projectService.includePackageJsonAutoImports() === PackageJsonAutoImportPreference.None ||
if (this.projectService.includePackageJsonAutoImports() === PackageJsonAutoImportPreference.Off ||
!this.languageServiceEnabled ||
isInsideNodeModules(this.currentDirectory) ||
!this.isDefaultProjectForOpenFiles()) {
return PackageJsonAutoImportPreference.None;
return PackageJsonAutoImportPreference.Off;
}
return this.projectService.includePackageJsonAutoImports();
}
@ -1831,6 +1831,9 @@ namespace ts.server {
export class AutoImportProviderProject extends Project {
private static readonly newName = createProjectNameFactoryWithCounter(makeAutoImportProviderProjectName);
/*@internal*/
private static readonly maxDependencies = 10;
/*@internal*/
static getRootFileNames(dependencySelection: PackageJsonAutoImportPreference, hostProject: Project, moduleResolutionHost: ModuleResolutionHost, compilerOptions: CompilerOptions): string[] {
if (!dependencySelection) {
@ -1844,9 +1847,6 @@ namespace ts.server {
for (const packageJson of packageJsons) {
packageJson.dependencies?.forEach((_, dependenyName) => addDependency(dependenyName));
packageJson.peerDependencies?.forEach((_, dependencyName) => addDependency(dependencyName));
if (dependencySelection === PackageJsonAutoImportPreference.All) {
packageJson.devDependencies?.forEach((_, dependencyName) => addDependency(dependencyName));
}
}
if (dependencyNames) {
@ -1862,6 +1862,10 @@ namespace ts.server {
const fileName = moduleResolutionHost.realpath?.(resolvedFileName) || resolvedFileName;
if (!hostProject.getCurrentProgram()!.getSourceFile(fileName) && !hostProject.getCurrentProgram()!.getSourceFile(resolvedFileName)) {
rootNames = append(rootNames, fileName);
// Avoid creating a large project that would significantly slow down time to editor interactivity
if (dependencySelection === PackageJsonAutoImportPreference.Auto && rootNames.length > this.maxDependencies) {
return ts.emptyArray;
}
}
}
}
@ -1877,7 +1881,7 @@ namespace ts.server {
/*@internal*/
static create(dependencySelection: PackageJsonAutoImportPreference, hostProject: Project, moduleResolutionHost: ModuleResolutionHost, documentRegistry: DocumentRegistry): AutoImportProviderProject | undefined {
if (dependencySelection === PackageJsonAutoImportPreference.None) {
if (dependencySelection === PackageJsonAutoImportPreference.Off) {
return undefined;
}
@ -1974,7 +1978,7 @@ namespace ts.server {
/*@internal*/
includePackageJsonAutoImports() {
return PackageJsonAutoImportPreference.None;
return PackageJsonAutoImportPreference.Off;
}
getTypeAcquisition(): TypeAcquisition {

View File

@ -3218,7 +3218,7 @@ namespace ts.server.protocol {
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly allowRenameOfImportPath?: boolean;
readonly includePackageJsonAutoImports?: "exclude-dev" | "all" | "none";
readonly includePackageJsonAutoImports?: "auto" | "on" | "off";
}
export interface CompilerOptions {

View File

@ -211,9 +211,9 @@ namespace ts {
/* @internal */
export const enum PackageJsonAutoImportPreference {
None,
ExcludeDevDependencies,
All
Off,
On,
Auto,
}
export interface PerformanceEvent {

View File

@ -229,6 +229,26 @@ namespace ts.projectSystem {
host.writeFile(packageJson.path, packageJson.content);
assert.ok(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider());
});
it("Does not create an auto import provider if there are too many dependencies", () => {
const createPackage = (i: number): File[] => ([
{ path: `/node_modules/package${i}/package.json`, content: `{ "name": "package${i}" }` },
{ path: `/node_modules/package${i}/index.d.ts`, content: `` }
]);
const packages = [];
for (let i = 0; i < 11; i++) {
packages.push(createPackage(i));
}
const dependencies = packages.reduce((hash, p) => ({ ...hash, [JSON.parse(p[0].content).name]: "*" }), {});
const packageJson: File = { path: "/package.json", content: JSON.stringify(dependencies) };
const { projectService, session } = setup([ ...flatten(packages), indexTs, tsconfig, packageJson ]);
openFilesForSession([indexTs], session);
const project = projectService.configuredProjects.get(tsconfig.path)!;
assert.isUndefined(project.getPackageJsonAutoImportProvider());
});
});
describe("unittests:: tsserver:: autoImportProvider - monorepo", () => {

View File

@ -544,7 +544,7 @@ namespace ts.projectSystem {
const otherFiles = [packageJson];
const host = createServerHost(projectFiles.concat(otherFiles));
const projectService = createProjectService(host);
projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "none" } });
projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "off" } });
const { configFileName } = projectService.openClientFile(app.path);
assert.equal(configFileName, tsconfigJson.path as server.NormalizedPath, `should find config`); // TODO: GH#18217
const recursiveWatchedDirectories: string[] = [`${appFolder}`, `${appFolder}/node_modules`].concat(getNodeModuleDirectories(getDirectoryPath(appFolder)));

View File

@ -130,7 +130,7 @@ namespace ts.projectSystem {
})();
const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer });
projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "none" } });
projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "off" } });
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });

View File

@ -3818,7 +3818,7 @@ declare namespace ts {
readonly importModuleSpecifierEnding?: "auto" | "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly includePackageJsonAutoImports?: "exclude-dev" | "all" | "none";
readonly includePackageJsonAutoImports?: "auto" | "on" | "off";
readonly provideRefactorNotApplicableReason?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */
@ -8897,7 +8897,7 @@ declare namespace ts.server.protocol {
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly allowRenameOfImportPath?: boolean;
readonly includePackageJsonAutoImports?: "exclude-dev" | "all" | "none";
readonly includePackageJsonAutoImports?: "auto" | "on" | "off";
}
interface CompilerOptions {
allowJs?: boolean;

View File

@ -3818,7 +3818,7 @@ declare namespace ts {
readonly importModuleSpecifierEnding?: "auto" | "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly includePackageJsonAutoImports?: "exclude-dev" | "all" | "none";
readonly includePackageJsonAutoImports?: "auto" | "on" | "off";
readonly provideRefactorNotApplicableReason?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */