mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
[WIP] send\receive install typing requests
This commit is contained in:
parent
959b6b6c07
commit
512ec04d29
@ -9,6 +9,14 @@ namespace ts.server {
|
||||
gzipSync(buf: Buffer): Buffer
|
||||
} = require("zlib");
|
||||
|
||||
interface NodeChildProcess {
|
||||
send(message: any, sendHandle?: any): void;
|
||||
}
|
||||
|
||||
const childProcess: {
|
||||
fork(modulePath: string): NodeChildProcess;
|
||||
} = require("child_process");
|
||||
|
||||
interface ReadLineOptions {
|
||||
input: NodeJS.ReadableStream;
|
||||
output?: NodeJS.WritableStream;
|
||||
@ -151,10 +159,65 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
class NodeTypingsInstaller implements ITypingsInstaller {
|
||||
private installer: NodeChildProcess;
|
||||
private session: Session;
|
||||
private cachePath: string;
|
||||
|
||||
constructor(private readonly logger: server.Logger) {
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
this.cachePath = normalizeSlashes(combinePaths(process.env.LOCALAPPDATA || process.env.APPDATA, "Microsoft/TypeScript"));
|
||||
break;
|
||||
case "darwin":
|
||||
case "linux":
|
||||
// TODO:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bind(session: Session) {
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
this.logger.info("Binding...")
|
||||
}
|
||||
|
||||
this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"));
|
||||
(<any>this.installer).on("message", (m: any) => this.handleMessage(m));
|
||||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions): void {
|
||||
const request: InstallTypingsRequest = {
|
||||
projectName: project.getProjectName(),
|
||||
fileNames: project.getFileNames(),
|
||||
compilerOptions: project.getCompilerOptions(),
|
||||
typingOptions,
|
||||
projectRootPath: <Path>(project.projectKind === ProjectKind.Inferred ? "" : getDirectoryPath(project.getProjectName())), // TODO: fixme
|
||||
safeListPath: <Path>(combinePaths(process.cwd(), "typingSafeList.json")), // TODO: fixme
|
||||
packageNameToTypingLocation: {}, // TODO: fixme
|
||||
cachePath: this.cachePath
|
||||
};
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
|
||||
}
|
||||
this.installer.send(request);
|
||||
}
|
||||
|
||||
C = 1;
|
||||
private handleMessage(response: InstallTypingsResponse) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Received response: ${JSON.stringify(response)}`)
|
||||
}
|
||||
require("fs").appendFileSync("E:\\sources\\git\\tss.txt", this.C + " !!!::" + JSON.stringify(response) + "\r\n");
|
||||
this.C++;
|
||||
this.session.onTypingsInstalled(response);
|
||||
require("fs").appendFileSync("E:\\sources\\git\\tss.txt", this.C + " !!!::" + "done" + "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
class IOSession extends Session {
|
||||
constructor(host: ServerHost, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean, logger: ts.server.Logger) {
|
||||
// TODO: fixme
|
||||
super(host, cancellationToken, useSingleInferredProject, undefined, Buffer.byteLength, maxUncompressedMessageSize, compress, process.hrtime, logger);
|
||||
constructor(host: ServerHost, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean, logger: server.Logger) {
|
||||
super(host, cancellationToken, useSingleInferredProject, new NodeTypingsInstaller(logger), Buffer.byteLength, maxUncompressedMessageSize, compress, process.hrtime, logger);
|
||||
(<NodeTypingsInstaller>this.typingsInstaller).bind(this);
|
||||
}
|
||||
|
||||
exit() {
|
||||
|
||||
@ -143,7 +143,7 @@ namespace ts.server {
|
||||
private host: ServerHost,
|
||||
cancellationToken: HostCancellationToken,
|
||||
useSingleInferredProject: boolean,
|
||||
typingsInstaller: ITypingsInstaller,
|
||||
protected readonly typingsInstaller: ITypingsInstaller,
|
||||
private byteLength: (buf: string, encoding?: string) => number,
|
||||
private maxUncompressedMessageSize: number,
|
||||
private compress: (s: string) => CompressedData,
|
||||
@ -1452,6 +1452,15 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
public onTypingsInstalled(response: InstallTypingsResponse) {
|
||||
const project = this.projectService.findProject(response.projectName);
|
||||
if (!project) {
|
||||
return;
|
||||
}
|
||||
this.projectService.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
|
||||
project.updateGraph();
|
||||
}
|
||||
|
||||
public onMessage(message: string) {
|
||||
this.gcTimer.scheduleCollect();
|
||||
let start: number[];
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
namespace ts.server {
|
||||
export interface ITypingsInstaller {
|
||||
enqueueInstallTypingsRequest(p: Project): void;
|
||||
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions): void;
|
||||
}
|
||||
|
||||
export const nullTypingsInstaller: ITypingsInstaller = {
|
||||
@ -12,7 +12,7 @@ namespace ts.server {
|
||||
class TypingsCacheEntry {
|
||||
readonly typingOptions: TypingOptions;
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
readonly typings: Path[];
|
||||
readonly typings: string[];
|
||||
}
|
||||
|
||||
const emptyArray: any[] = [];
|
||||
@ -88,11 +88,19 @@ namespace ts.server {
|
||||
|
||||
const entry = this.perProjectCache[project.getProjectName()];
|
||||
if (!entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions)) {
|
||||
this.installer.enqueueInstallTypingsRequest(project);
|
||||
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
|
||||
}
|
||||
return entry ? entry.typings : emptyArray;
|
||||
}
|
||||
|
||||
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, newTypings: string[]) {
|
||||
this.perProjectCache[projectName] = {
|
||||
compilerOptions,
|
||||
typingOptions,
|
||||
typings: newTypings
|
||||
};
|
||||
}
|
||||
|
||||
deleteTypingsForProject(project: Project) {
|
||||
delete this.perProjectCache[project.getProjectName()];
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
namespace ts.server.typingsInstaller {
|
||||
export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
private execSync: { (command: string, options: { stdio: "ignore" }): any };
|
||||
private exec: { (command: string, options: {}, callback?: (error: Error, stdout: string, stderr: string) => void): any };
|
||||
private exec: { (command: string, options: { cwd: string }, callback?: (error: Error, stdout: string, stderr: string) => void): any };
|
||||
constructor() {
|
||||
super();
|
||||
this.execSync = require("child_process").execSync;
|
||||
@ -13,14 +13,14 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
init() {
|
||||
super.init();
|
||||
process.on("install", (req: InstallTypingsRequest) => {
|
||||
process.on("message", (req: InstallTypingsRequest) => {
|
||||
this.install(req);
|
||||
})
|
||||
}
|
||||
|
||||
protected isPackageInstalled(packageName: string) {
|
||||
try {
|
||||
this.execSync(`npm list --global --depth=1 ${name}`, { stdio: "ignore" });
|
||||
this.execSync(`npm list --global --depth=1 ${packageName}`, { stdio: "ignore" });
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
@ -30,7 +30,7 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
protected installPackage(packageName: string) {
|
||||
try {
|
||||
this.execSync(`npm install --global ${name}`, { stdio: "ignore" });
|
||||
this.execSync(`npm install --global ${packageName}`, { stdio: "ignore" });
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
@ -42,12 +42,17 @@ namespace ts.server.typingsInstaller {
|
||||
return sys;
|
||||
}
|
||||
|
||||
C = 1;
|
||||
|
||||
protected sendResponse(response: InstallTypingsResponse) {
|
||||
(<any>response).___id = [this.C];
|
||||
this.C++;
|
||||
log("sendResponse::" + JSON.stringify(response));
|
||||
process.send(response);
|
||||
}
|
||||
|
||||
protected runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void {
|
||||
this.exec(`tsd install ${typingsToInstall.join(" ")} -ros`, {}, (err, stdout, stderr) => {
|
||||
this.exec(`tsd install ${typingsToInstall.join(" ")} -ros`, { cwd: cachePath }, (err, stdout, stderr) => {
|
||||
const i = stdout.indexOf("running install");
|
||||
if (i < 0) {
|
||||
return;
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
/// <reference path="../types.d.ts"/>
|
||||
|
||||
namespace ts.server.typingsInstaller {
|
||||
|
||||
export function log(s: string) {
|
||||
require("fs").appendFileSync("E:\\sources\\git\\installer.txt", s + "\r\n");
|
||||
}
|
||||
const DefaultTsdSettings = JSON.stringify({
|
||||
version: "v4",
|
||||
repo: "DefinitelyTyped/DefinitelyTyped",
|
||||
@ -20,6 +22,7 @@ namespace ts.server.typingsInstaller {
|
||||
if (!this.isTsdInstalled) {
|
||||
this.isTsdInstalled = this.installPackage("tsd");
|
||||
}
|
||||
log(`start ${this.isTsdInstalled}`);
|
||||
}
|
||||
|
||||
install(req: InstallTypingsRequest) {
|
||||
@ -27,6 +30,7 @@ namespace ts.server.typingsInstaller {
|
||||
return;
|
||||
}
|
||||
|
||||
log(`install ${JSON.stringify(req)}`);
|
||||
const discoverTypingsResult = JsTyping.discoverTypings(
|
||||
this.getInstallTypingHost(),
|
||||
req.fileNames,
|
||||
@ -36,6 +40,7 @@ namespace ts.server.typingsInstaller {
|
||||
req.typingOptions,
|
||||
req.compilerOptions);
|
||||
|
||||
log(`install ${JSON.stringify(discoverTypingsResult)}`);
|
||||
// respond with whatever cached typings we have now
|
||||
this.sendResponse(this.createResponse(req, discoverTypingsResult.cachedTypingPaths));
|
||||
// start watching files
|
||||
@ -46,6 +51,7 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
private installTypings(req: InstallTypingsRequest, currentlyCachedTypings: string[], typingsToInstall: string[]) {
|
||||
typingsToInstall = filter(typingsToInstall, x => !hasProperty(this.missingTypings, x));
|
||||
log(`install ${JSON.stringify(typingsToInstall)}`);
|
||||
if (typingsToInstall.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -57,9 +63,11 @@ namespace ts.server.typingsInstaller {
|
||||
host.writeFile(tsdPath, DefaultTsdSettings);
|
||||
}
|
||||
|
||||
this.runTsd(tsdPath, typingsToInstall, installedTypings => {
|
||||
this.runTsd(req.cachePath, typingsToInstall, installedTypings => {
|
||||
// TODO: record new missing package names
|
||||
// TODO: watch project directory
|
||||
installedTypings = installedTypings.map(x => getNormalizedAbsolutePath(x, req.cachePath));
|
||||
log(`include ${JSON.stringify(installedTypings)}`);
|
||||
this.sendResponse(this.createResponse(req, currentlyCachedTypings.concat(installedTypings)));
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user