220 lines
12 KiB
Plaintext
220 lines
12 KiB
Plaintext
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.createAutoImportProviderProjectStatic = void 0;
|
||
|
const project_1 = require("./project");
|
||
|
function createAutoImportProviderProjectStatic(tsBase, host, createLanguageService) {
|
||
|
const ts = tsBase;
|
||
|
const { combinePaths, inferredTypesContainingFile, arrayFrom, resolvePackageNameToPackageJson, concatenate, forEach, startsWith, getEntrypointsFromPackageJsonInfo, mapDefined, timestamp, } = ts;
|
||
|
return {
|
||
|
maxDependencies: 10,
|
||
|
compilerOptionsOverrides: {
|
||
|
diagnostics: false,
|
||
|
skipLibCheck: true,
|
||
|
sourceMap: false,
|
||
|
types: ts.emptyArray,
|
||
|
lib: ts.emptyArray,
|
||
|
noLib: true,
|
||
|
},
|
||
|
getRootFileNames(dependencySelection, hostProject, moduleResolutionHost, compilerOptions) {
|
||
|
var _a, _b;
|
||
|
if (!dependencySelection) {
|
||
|
return ts.emptyArray;
|
||
|
}
|
||
|
const program = hostProject.getCurrentProgram();
|
||
|
if (!program) {
|
||
|
return ts.emptyArray;
|
||
|
}
|
||
|
const start = timestamp();
|
||
|
let dependencyNames;
|
||
|
let rootNames;
|
||
|
const rootFileName = combinePaths(hostProject.currentDirectory, inferredTypesContainingFile);
|
||
|
const packageJsons = hostProject.getPackageJsonsForAutoImport(combinePaths(hostProject.currentDirectory, rootFileName));
|
||
|
for (const packageJson of packageJsons) {
|
||
|
(_a = packageJson.dependencies) === null || _a === void 0 ? void 0 : _a.forEach((_, dependenyName) => addDependency(dependenyName));
|
||
|
(_b = packageJson.peerDependencies) === null || _b === void 0 ? void 0 : _b.forEach((_, dependencyName) => addDependency(dependencyName));
|
||
|
}
|
||
|
let dependenciesAdded = 0;
|
||
|
if (dependencyNames) {
|
||
|
const symlinkCache = hostProject.getSymlinkCache();
|
||
|
for (const name of arrayFrom(dependencyNames.keys())) {
|
||
|
// Avoid creating a large project that would significantly slow down time to editor interactivity
|
||
|
if (dependencySelection === 2 /* PackageJsonAutoImportPreference.Auto */ && dependenciesAdded > this.maxDependencies) {
|
||
|
hostProject.log(`AutoImportProviderProject: attempted to add more than ${this.maxDependencies} dependencies. Aborting.`);
|
||
|
return ts.emptyArray;
|
||
|
}
|
||
|
// 1. Try to load from the implementation package. For many dependencies, the
|
||
|
// package.json will exist, but the package will not contain any typings,
|
||
|
// so `entrypoints` will be undefined. In that case, or if the dependency
|
||
|
// is missing altogether, we will move on to trying the @types package (2).
|
||
|
const packageJson = resolvePackageNameToPackageJson(name, hostProject.currentDirectory, compilerOptions, moduleResolutionHost,
|
||
|
// @ts-expect-error
|
||
|
program.getModuleResolutionCache());
|
||
|
if (packageJson) {
|
||
|
const entrypoints = getRootNamesFromPackageJson(packageJson, program, symlinkCache);
|
||
|
if (entrypoints) {
|
||
|
rootNames = concatenate(rootNames, entrypoints);
|
||
|
dependenciesAdded += entrypoints.length ? 1 : 0;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
// 2. Try to load from the @types package in the tree and in the global
|
||
|
// typings cache location, if enabled.
|
||
|
// @ts-expect-error
|
||
|
const done = forEach([hostProject.currentDirectory, hostProject.getGlobalTypingsCacheLocation()], (directory) => {
|
||
|
if (directory) {
|
||
|
const typesPackageJson = resolvePackageNameToPackageJson(`@types/${name}`, directory, compilerOptions, moduleResolutionHost,
|
||
|
// @ts-expect-error
|
||
|
program.getModuleResolutionCache());
|
||
|
if (typesPackageJson) {
|
||
|
const entrypoints = getRootNamesFromPackageJson(typesPackageJson, program, symlinkCache);
|
||
|
rootNames = concatenate(rootNames, entrypoints);
|
||
|
dependenciesAdded += (entrypoints === null || entrypoints === void 0 ? void 0 : entrypoints.length) ? 1 : 0;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
if (done)
|
||
|
continue;
|
||
|
// 3. If the @types package did not exist and the user has settings that
|
||
|
// allow processing JS from node_modules, go back to the implementation
|
||
|
// package and load the JS.
|
||
|
if (packageJson && compilerOptions.allowJs && compilerOptions.maxNodeModuleJsDepth) {
|
||
|
const entrypoints = getRootNamesFromPackageJson(packageJson, program, symlinkCache, /*allowJs*/ true);
|
||
|
rootNames = concatenate(rootNames, entrypoints);
|
||
|
dependenciesAdded += (entrypoints === null || entrypoints === void 0 ? void 0 : entrypoints.length) ? 1 : 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (rootNames === null || rootNames === void 0 ? void 0 : rootNames.length) {
|
||
|
hostProject.log(`AutoImportProviderProject: found ${rootNames.length} root files in ${dependenciesAdded} dependencies in ${timestamp() - start} ms`);
|
||
|
}
|
||
|
return rootNames || ts.emptyArray;
|
||
|
function addDependency(dependency) {
|
||
|
if (!startsWith(dependency, '@types/')) {
|
||
|
(dependencyNames || (dependencyNames = new Set())).add(dependency);
|
||
|
}
|
||
|
}
|
||
|
function getRootNamesFromPackageJson(packageJson, program, symlinkCache, resolveJs) {
|
||
|
var _a;
|
||
|
const entrypoints = getEntrypointsFromPackageJsonInfo(packageJson, compilerOptions, moduleResolutionHost,
|
||
|
// @ts-expect-error
|
||
|
program.getModuleResolutionCache(), resolveJs);
|
||
|
if (entrypoints) {
|
||
|
const real = (_a = moduleResolutionHost.realpath) === null || _a === void 0 ? void 0 : _a.call(moduleResolutionHost, packageJson.packageDirectory);
|
||
|
const isSymlink = real && real !== packageJson.packageDirectory;
|
||
|
if (isSymlink) {
|
||
|
symlinkCache.setSymlinkedDirectory(packageJson.packageDirectory, {
|
||
|
real,
|
||
|
realPath: hostProject.toPath(real),
|
||
|
});
|
||
|
}
|
||
|
// @ts-expect-error
|
||
|
return mapDefined(entrypoints, (entrypoint) => {
|
||
|
const resolvedFileName = isSymlink ? entrypoint.replace(packageJson.packageDirectory, real) : entrypoint;
|
||
|
if (!program.getSourceFile(resolvedFileName) && !(isSymlink && program.getSourceFile(entrypoint))) {
|
||
|
return resolvedFileName;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
create(dependencySelection, hostProject, moduleResolutionHost) {
|
||
|
if (dependencySelection === 0 /* PackageJsonAutoImportPreference.Off */) {
|
||
|
return undefined;
|
||
|
}
|
||
|
const compilerOptions = Object.assign(Object.assign({}, hostProject.getCompilerOptions()), this.compilerOptionsOverrides);
|
||
|
let rootNames = this.getRootFileNames(dependencySelection, hostProject, moduleResolutionHost, compilerOptions);
|
||
|
if (!rootNames.length) {
|
||
|
return undefined;
|
||
|
}
|
||
|
return createAutoImportProviderProject(tsBase, host, createLanguageService, { self: this, hostProject, rootNames, compilerOptions });
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
exports.createAutoImportProviderProjectStatic = createAutoImportProviderProjectStatic;
|
||
|
function createAutoImportProviderProject(tsBase, host, createLanguageService, options) {
|
||
|
const { self, rootNames, compilerOptions, hostProject } = options;
|
||
|
const ts = tsBase;
|
||
|
const { some } = ts;
|
||
|
const project = Object.assign(Object.assign({}, (0, project_1.createProject)(tsBase, host, createLanguageService, {
|
||
|
projectService: hostProject.projectService,
|
||
|
currentDirectory: hostProject.currentDirectory,
|
||
|
compilerOptions,
|
||
|
})), { projectVersion: 0, getProjectVersion() {
|
||
|
return this.projectVersion.toString();
|
||
|
}, rootFileNames: rootNames, hostProject,
|
||
|
isEmpty() {
|
||
|
return !some(this.rootFileNames);
|
||
|
},
|
||
|
isOrphan() {
|
||
|
return true;
|
||
|
},
|
||
|
updateGraph() {
|
||
|
var _a;
|
||
|
let rootFileNames = this.rootFileNames;
|
||
|
if (!rootFileNames) {
|
||
|
rootFileNames = self.getRootFileNames(this.hostProject.includePackageJsonAutoImports(), this.hostProject, this.hostProject.getModuleResolutionHostForAutoImportProvider(), this.getCompilationSettings());
|
||
|
}
|
||
|
this.rootFileNames = rootFileNames;
|
||
|
const oldProgram = this.getCurrentProgram();
|
||
|
this.program = (_a = this.languageService) === null || _a === void 0 ? void 0 : _a.getProgram();
|
||
|
this.dirty = false;
|
||
|
if (oldProgram && oldProgram !== this.getCurrentProgram()) {
|
||
|
this.hostProject.clearCachedExportInfoMap();
|
||
|
}
|
||
|
},
|
||
|
scheduleInvalidateResolutionsOfFailedLookupLocations() {
|
||
|
// Invalidation will happen on-demand as part of updateGraph
|
||
|
return;
|
||
|
},
|
||
|
hasRoots() {
|
||
|
var _a;
|
||
|
return !!((_a = this.rootFileNames) === null || _a === void 0 ? void 0 : _a.length);
|
||
|
},
|
||
|
markAsDirty() {
|
||
|
if (!this.dirty) {
|
||
|
this.rootFileNames = undefined;
|
||
|
this.projectVersion++;
|
||
|
this.dirty = true;
|
||
|
}
|
||
|
},
|
||
|
getScriptFileNames() {
|
||
|
return this.rootFileNames || ts.emptyArray;
|
||
|
},
|
||
|
getLanguageService() {
|
||
|
throw new Error("AutoImportProviderProject language service should never be used. To get the program, use `project.getCurrentProgram()`.");
|
||
|
},
|
||
|
onAutoImportProviderSettingsChanged() {
|
||
|
throw new Error("AutoImportProviderProject is an auto import provider; use `markAsDirty()` instead.");
|
||
|
},
|
||
|
onPackageJsonChange() {
|
||
|
throw new Error("package.json changes should be notified on an AutoImportProvider's host project");
|
||
|
},
|
||
|
getModuleResolutionHostForAutoImportProvider() {
|
||
|
throw new Error("AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead.");
|
||
|
},
|
||
|
includePackageJsonAutoImports() {
|
||
|
return 0 /* PackageJsonAutoImportPreference.Off */;
|
||
|
},
|
||
|
getTypeAcquisition() {
|
||
|
return { enable: false };
|
||
|
},
|
||
|
getSymlinkCache() {
|
||
|
return this.hostProject.getSymlinkCache();
|
||
|
},
|
||
|
getModuleResolutionCache() {
|
||
|
var _a, _b;
|
||
|
// @ts-expect-error
|
||
|
return (_b = (_a = this.hostProject.languageService) === null || _a === void 0 ? void 0 : _a.getProgram()) === null || _b === void 0 ? void 0 : _b.getModuleResolutionCache();
|
||
|
} });
|
||
|
return (0, project_1.initProject)(project, new Proxy(host, {
|
||
|
get(target, key) {
|
||
|
return key in project ? project[key] : target[key];
|
||
|
},
|
||
|
set(_target, key, value) {
|
||
|
project[key] = value;
|
||
|
return true;
|
||
|
}
|
||
|
}), createLanguageService);
|
||
|
}
|