move global cache location to node typings installer
This commit is contained in:
parent
f603f024ba
commit
672813afb6
|
@ -29,15 +29,12 @@ namespace ts {
|
|||
|
||||
abstract class TestTypingsInstaller extends server.typingsInstaller.TypingsInstaller implements server.ITypingsInstaller {
|
||||
protected projectService: server.ProjectService;
|
||||
constructor(private readonly host: server.ServerHost) {
|
||||
super();
|
||||
constructor(readonly cachePath: string, readonly installTypingHost: server.ServerHost) {
|
||||
super(cachePath, <Path>"");
|
||||
this.init();
|
||||
}
|
||||
|
||||
abstract cachePath: string;
|
||||
safeFileList = <Path>"";
|
||||
packageNameToTypingLocation: Map<string> = createMap<string>();
|
||||
|
||||
postInstallActions: (( map: (t: string[]) => string[]) => void)[] = [];
|
||||
|
||||
runPostInstallActions(map: (t: string[]) => string[]) {
|
||||
|
@ -52,7 +49,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
getInstallTypingHost() {
|
||||
return this.host;
|
||||
return this.installTypingHost;
|
||||
}
|
||||
|
||||
installPackage(packageName: string) {
|
||||
|
@ -74,7 +71,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
|
||||
const request = server.createInstallTypingsRequest(project, typingOptions, this.safeFileList, this.packageNameToTypingLocation, this.cachePath);
|
||||
const request = server.createInstallTypingsRequest(project, typingOptions, this.cachePath);
|
||||
this.install(request);
|
||||
}
|
||||
}
|
||||
|
@ -1519,9 +1516,8 @@ namespace ts {
|
|||
|
||||
const host = createServerHost([file1, tsconfig, packageJson]);
|
||||
class TypingInstaller extends TestTypingsInstaller {
|
||||
cachePath = "/a/data/";
|
||||
constructor(host: server.ServerHost) {
|
||||
super(host);
|
||||
super("/a/data/", host);
|
||||
}
|
||||
};
|
||||
const installer = new TypingInstaller(host);
|
||||
|
|
|
@ -18,10 +18,6 @@ namespace ts.server {
|
|||
fork(modulePath: string): NodeChildProcess;
|
||||
} = require("child_process");
|
||||
|
||||
const os: {
|
||||
homedir(): string
|
||||
} = require("os");
|
||||
|
||||
interface ReadLineOptions {
|
||||
input: NodeJS.ReadableStream;
|
||||
output?: NodeJS.WritableStream;
|
||||
|
@ -167,24 +163,8 @@ namespace ts.server {
|
|||
class NodeTypingsInstaller implements ITypingsInstaller {
|
||||
private installer: NodeChildProcess;
|
||||
private projectService: ProjectService;
|
||||
private cachePath: string;
|
||||
|
||||
constructor(private readonly logger: server.Logger) {
|
||||
let basePath: string;
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
basePath = process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir();
|
||||
break;
|
||||
case "linux":
|
||||
basePath = os.homedir();
|
||||
break;
|
||||
case "darwin":
|
||||
basePath = combinePaths(os.homedir(), "Library/Application Support/")
|
||||
break;
|
||||
}
|
||||
if (basePath) {
|
||||
this.cachePath = combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript");
|
||||
}
|
||||
}
|
||||
|
||||
attach(projectService: ProjectService) {
|
||||
|
@ -198,13 +178,7 @@ namespace ts.server {
|
|||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions): void {
|
||||
const request = createInstallTypingsRequest(
|
||||
project,
|
||||
typingOptions,
|
||||
/*safeListPath*/ <Path>(combinePaths(process.cwd(), "typingSafeList.json")), // TODO: fixme
|
||||
/*packageNameToTypingLocation*/ createMap<string>(), // TODO: fixme
|
||||
this.cachePath
|
||||
);
|
||||
const request = createInstallTypingsRequest(project, typingOptions);
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
|
||||
}
|
||||
|
|
4
src/server/types.d.ts
vendored
4
src/server/types.d.ts
vendored
|
@ -7,11 +7,9 @@ declare namespace ts.server {
|
|||
readonly projectName: string;
|
||||
readonly fileNames: string[];
|
||||
readonly projectRootPath: ts.Path;
|
||||
readonly safeListPath: ts.Path;
|
||||
readonly packageNameToTypingLocation: ts.Map<string>;
|
||||
readonly typingOptions: ts.TypingOptions;
|
||||
readonly compilerOptions: ts.CompilerOptions;
|
||||
readonly cachePath: string;
|
||||
readonly cachePath?: string;
|
||||
}
|
||||
|
||||
export interface CompressedData {
|
||||
|
|
|
@ -2,13 +2,39 @@
|
|||
/// <reference types="node" />
|
||||
|
||||
namespace ts.server.typingsInstaller {
|
||||
|
||||
const os: {
|
||||
homedir(): string
|
||||
} = require("os");
|
||||
|
||||
function getGlobalCacheLocation() {
|
||||
let basePath: string;
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
basePath = process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir();
|
||||
break;
|
||||
case "linux":
|
||||
basePath = os.homedir();
|
||||
break;
|
||||
case "darwin":
|
||||
basePath = combinePaths(os.homedir(), "Library/Application Support/")
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.assert(basePath !== undefined);
|
||||
return combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript");
|
||||
}
|
||||
|
||||
export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
private execSync: { (command: string, options: { stdio: "ignore" }): any };
|
||||
private exec: { (command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any };
|
||||
readonly installTypingHost: InstallTypingHost = sys;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.execSync = require("child_process").execSync;
|
||||
this.exec = require("child_process").exec;
|
||||
super(getGlobalCacheLocation(), toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)));
|
||||
const { exec, execSync } = require("child_process");
|
||||
this.execSync = execSync;
|
||||
this.exec = exec;
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -38,10 +64,6 @@ namespace ts.server.typingsInstaller {
|
|||
}
|
||||
}
|
||||
|
||||
protected getInstallTypingHost() {
|
||||
return sys;
|
||||
}
|
||||
|
||||
protected sendResponse(response: InstallTypingsResponse) {
|
||||
process.send(response);
|
||||
}
|
||||
|
|
|
@ -9,16 +9,38 @@ namespace ts.server.typingsInstaller {
|
|||
path: "typings"
|
||||
}, /*replacer*/undefined, /*space*/4);
|
||||
|
||||
interface TsdConfig {
|
||||
installed: MapLike<any>;
|
||||
}
|
||||
|
||||
function tsdTypingToFileName(cachePath: string, tsdTypingFile: string) {
|
||||
return combinePaths(cachePath, `typings/${tsdTypingFile}`);
|
||||
}
|
||||
|
||||
function getPackageName(tsdTypingFile: string) {
|
||||
const idx = tsdTypingFile.indexOf("/");
|
||||
return idx > 0 ? tsdTypingFile.substr(0, idx) : undefined;
|
||||
}
|
||||
|
||||
export abstract class TypingsInstaller {
|
||||
|
||||
private isTsdInstalled: boolean;
|
||||
private missingTypings: Map<string> = createMap<string>();
|
||||
|
||||
private packageNameToTypingLocation: Map<string> = createMap<string>();
|
||||
private missingTypingsSet: Map<true> = createMap<true>();
|
||||
private knownCachesSet: Map<true> = createMap<true>();
|
||||
|
||||
abstract readonly installTypingHost: InstallTypingHost;
|
||||
|
||||
constructor(readonly globalCachePath: string, readonly safeListPath: Path) {
|
||||
}
|
||||
|
||||
init() {
|
||||
this.isTsdInstalled = this.isPackageInstalled("tsd");
|
||||
if (!this.isTsdInstalled) {
|
||||
this.isTsdInstalled = this.installPackage("tsd");
|
||||
}
|
||||
this.processCacheLocation(this.globalCachePath);
|
||||
}
|
||||
|
||||
install(req: InstallTypingsRequest) {
|
||||
|
@ -26,43 +48,91 @@ namespace ts.server.typingsInstaller {
|
|||
return;
|
||||
}
|
||||
|
||||
// load existing typing information from the cache
|
||||
if (req.cachePath) {
|
||||
this.processCacheLocation(req.cachePath);
|
||||
}
|
||||
|
||||
const discoverTypingsResult = JsTyping.discoverTypings(
|
||||
this.getInstallTypingHost(),
|
||||
this.installTypingHost,
|
||||
req.fileNames,
|
||||
req.projectRootPath,
|
||||
req.safeListPath,
|
||||
req.packageNameToTypingLocation,
|
||||
this.safeListPath,
|
||||
this.packageNameToTypingLocation,
|
||||
req.typingOptions,
|
||||
req.compilerOptions);
|
||||
|
||||
// respond with whatever cached typings we have now
|
||||
this.sendResponse(this.createResponse(req, discoverTypingsResult.cachedTypingPaths));
|
||||
|
||||
// start watching files
|
||||
this.watchFiles(discoverTypingsResult.filesToWatch);
|
||||
|
||||
// install typings and
|
||||
this.installTypings(req, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames);
|
||||
}
|
||||
|
||||
private processCacheLocation(cacheLocation: string) {
|
||||
if (this.knownCachesSet[cacheLocation]) {
|
||||
return;
|
||||
}
|
||||
const tsdJson = combinePaths(cacheLocation, "tsd.json");
|
||||
if (this.installTypingHost.fileExists(tsdJson)) {
|
||||
const tsdConfig = <TsdConfig>JSON.parse(this.installTypingHost.readFile(tsdJson));
|
||||
if (tsdConfig.installed) {
|
||||
for (const key in tsdConfig.installed) {
|
||||
// key is <package name>/<typing file>
|
||||
const packageName = getPackageName(key);
|
||||
if (!packageName) {
|
||||
continue;
|
||||
}
|
||||
const typingFile = tsdTypingToFileName(cacheLocation, key);
|
||||
const existingTypingFile = this.packageNameToTypingLocation[packageName];
|
||||
if (existingTypingFile === typingFile) {
|
||||
continue;
|
||||
}
|
||||
if (existingTypingFile) {
|
||||
// TODO: log warning
|
||||
}
|
||||
this.packageNameToTypingLocation[packageName] = typingFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.knownCachesSet[cacheLocation] = true;
|
||||
}
|
||||
|
||||
private installTypings(req: InstallTypingsRequest, currentlyCachedTypings: string[], typingsToInstall: string[]) {
|
||||
typingsToInstall = filter(typingsToInstall, x => !hasProperty(this.missingTypings, x));
|
||||
typingsToInstall = filter(typingsToInstall, x => !this.missingTypingsSet[x]);
|
||||
if (typingsToInstall.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: install typings and send response when they are ready
|
||||
const host = this.getInstallTypingHost();
|
||||
const tsdPath = combinePaths(req.cachePath, "tsd.json");
|
||||
if (!host.fileExists(tsdPath)) {
|
||||
this.ensureDirectoryExists(req.cachePath, host);
|
||||
host.writeFile(tsdPath, DefaultTsdSettings);
|
||||
if (!this.installTypingHost.fileExists(tsdPath)) {
|
||||
this.ensureDirectoryExists(req.cachePath, this.installTypingHost);
|
||||
this.installTypingHost.writeFile(tsdPath, DefaultTsdSettings);
|
||||
}
|
||||
|
||||
this.runTsd(req.cachePath, typingsToInstall, installedTypings => {
|
||||
// TODO: record new missing package names
|
||||
// TODO: watch project directory
|
||||
const typingDirectory = combinePaths(req.cachePath, "typings");
|
||||
installedTypings = installedTypings.map(x => combinePaths(typingDirectory, x));
|
||||
this.sendResponse(this.createResponse(req, currentlyCachedTypings.concat(installedTypings)));
|
||||
const installedPackages: Map<true> = createMap<true>();
|
||||
const installedTypingFiles: string[] = [];
|
||||
for (const t of installedTypings) {
|
||||
const packageName = getPackageName(t);
|
||||
if (!packageName) {
|
||||
continue;
|
||||
}
|
||||
installedPackages[packageName] = true;
|
||||
installedTypingFiles.push(tsdTypingToFileName(req.cachePath, t));
|
||||
}
|
||||
for (const toInstall of typingsToInstall) {
|
||||
if (!installedPackages[toInstall]) {
|
||||
this.missingTypingsSet[toInstall] = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.sendResponse(this.createResponse(req, currentlyCachedTypings.concat(installedTypingFiles)));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -91,7 +161,6 @@ namespace ts.server.typingsInstaller {
|
|||
|
||||
protected abstract isPackageInstalled(packageName: string): boolean;
|
||||
protected abstract installPackage(packageName: string): boolean;
|
||||
protected abstract getInstallTypingHost(): InstallTypingHost;
|
||||
protected abstract sendResponse(response: InstallTypingsResponse): void;
|
||||
protected abstract runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="types.d.ts" />
|
||||
|
||||
namespace ts.server {
|
||||
|
@ -30,15 +29,13 @@ namespace ts.server {
|
|||
export type Types = Err | Info | Perf;
|
||||
}
|
||||
|
||||
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, safeListPath: Path, packageNameToTypingLocation: Map<string>, cachePath: string): InstallTypingsRequest {
|
||||
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, cachePath?: string): InstallTypingsRequest {
|
||||
return {
|
||||
projectName: project.getProjectName(),
|
||||
fileNames: project.getFileNames(),
|
||||
compilerOptions: project.getCompilerOptions(),
|
||||
typingOptions,
|
||||
projectRootPath: <Path>(project.projectKind === ProjectKind.Inferred ? "" : getDirectoryPath(project.getProjectName())), // TODO: fixme
|
||||
safeListPath,
|
||||
packageNameToTypingLocation,
|
||||
cachePath
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue