From ab1512fb1360a33007c891ddc2030b1f507041bc Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 9 Jun 2015 17:00:35 -0700 Subject: [PATCH 1/4] Export server & session without any node specifics --- Jakefile.js | 24 ++++++++++++++++++++ src/harness/harnessLanguageService.ts | 2 +- src/server/editorServices.ts | 29 ++++++++++++------------ src/server/nodeimpl.ts | 7 ++++++ src/server/server.ts | 10 ++++----- src/server/session.ts | 32 +++++++++++++++++++-------- src/server/tsconfig.json | 1 + 7 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 src/server/nodeimpl.ts diff --git a/Jakefile.js b/Jakefile.js index 9b95744d392..9a2f39ee130 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -100,11 +100,20 @@ var serverSources = [ "editorServices.ts", "protocol.d.ts", "session.ts", + "nodeimpl.ts", "server.ts" ].map(function (f) { return path.join(serverDirectory, f); }); +var languageServiceLibrarySources = [ + "editorServices.ts", + "protocol.d.ts", + "session.ts" +].map(function (f) { + return path.join(serverDirectory, f); +}); + var harnessSources = [ "harness.ts", "sourceMapRecorder.ts", @@ -137,6 +146,7 @@ var harnessSources = [ "protocol.d.ts", "session.ts", "client.ts", + "nodeimpl.ts", "editorServices.ts", ].map(function (f) { return path.join(serverDirectory, f); @@ -369,6 +379,20 @@ compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].conca var serverFile = path.join(builtLocalDirectory, "tsserver.js"); compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true); +var lsslFile = path.join(builtLocalDirectory, "tslssl.js"); +compileFile( + lsslFile, + languageServiceLibrarySources, + [builtLocalDirectory, copyright].concat(serverSources).concat(languageServiceLibrarySources), + /*prefixes*/ [copyright], + /*useBuiltCompiler*/ true, + /*noOutFile*/ false, + /*generateDeclarations*/ true); + +// Local target to build the language service server library +desc("Builds language service server library"); +task("lssl", [lsslFile]); + // Local target to build the compiler and services desc("Builds the full compiler and services"); task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile]); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 0e0b8d82918..3796c84863b 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -583,7 +583,7 @@ module Harness.LanguageService { // This host is just a proxy for the clientHost, it uses the client // host to answer server queries about files on disk var serverHost = new SessionServerHost(clientHost); - var server = new ts.server.Session(serverHost, serverHost); + var server = new ts.server.Session(serverHost, new ts.server.NodeEnvironment(), serverHost); // Fake the connection between the client and the server serverHost.writeMessage = client.onMessage.bind(client); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index bc9e685825c..ffb22cc505b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -2,7 +2,6 @@ /// /// /// -/// module ts.server { export interface Logger { @@ -28,7 +27,7 @@ module ts.server { }); } - class ScriptInfo { + export class ScriptInfo { svc: ScriptVersionCache; children: ScriptInfo[] = []; // files referenced by this file defaultProject: Project; // project to use by default for file @@ -80,7 +79,7 @@ module ts.server { } } - class LSHost implements ts.LanguageServiceHost { + export class LSHost implements ts.LanguageServiceHost { ls: ts.LanguageService = null; compilationSettings: ts.CompilerOptions; filenameToScript: ts.Map = {}; @@ -273,7 +272,7 @@ module ts.server { } } - interface ProjectOptions { + export interface ProjectOptions { // these fields can be present in the project file files?: string[]; compilerOptions?: ts.CompilerOptions; @@ -376,7 +375,7 @@ module ts.server { } } - interface ProjectOpenResult { + export interface ProjectOpenResult { success?: boolean; errorMsg?: string; project?: Project; @@ -392,11 +391,11 @@ module ts.server { return copiedList; } - interface ProjectServiceEventHandler { + export interface ProjectServiceEventHandler { (eventName: string, project: Project, fileName: string): void; } - interface HostConfiguration { + export interface HostConfiguration { formatCodeOptions: ts.FormatCodeOptions; hostInfo: string; } @@ -953,7 +952,7 @@ module ts.server { } - class CompilerService { + export class CompilerService { host: LSHost; languageService: ts.LanguageService; classifier: ts.Classifier; @@ -999,7 +998,7 @@ module ts.server { } - interface LineCollection { + export interface LineCollection { charCount(): number; lineCount(): number; isLeaf(): boolean; @@ -1013,7 +1012,7 @@ module ts.server { leaf?: LineLeaf; } - enum CharRangeSection { + export enum CharRangeSection { PreStart, Start, Entire, @@ -1022,7 +1021,7 @@ module ts.server { PostEnd } - interface ILineIndexWalker { + export interface ILineIndexWalker { goSubtree: boolean; done: boolean; leaf(relativeStart: number, relativeLength: number, lineCollection: LineLeaf): void; @@ -1248,7 +1247,7 @@ module ts.server { } // text change information - class TextChange { + export class TextChange { constructor(public pos: number, public deleteLen: number, public insertedText?: string) { } @@ -1371,7 +1370,7 @@ module ts.server { } } - class LineIndexSnapshot implements ts.IScriptSnapshot { + export class LineIndexSnapshot implements ts.IScriptSnapshot { index: LineIndex; changesSincePreviousVersion: TextChange[] = []; @@ -1605,7 +1604,7 @@ module ts.server { } } - class LineNode implements LineCollection { + export class LineNode implements LineCollection { totalChars = 0; totalLines = 0; children: LineCollection[] = []; @@ -1891,7 +1890,7 @@ module ts.server { } } - class LineLeaf implements LineCollection { + export class LineLeaf implements LineCollection { udata: any; constructor(public text: string) { diff --git a/src/server/nodeimpl.ts b/src/server/nodeimpl.ts new file mode 100644 index 00000000000..9694b49aa85 --- /dev/null +++ b/src/server/nodeimpl.ts @@ -0,0 +1,7 @@ +/// +module ts.server { + export class NodeEnvironment implements Environment { + byteLength = Buffer.byteLength; + hrtime = process.hrtime; + } +} \ No newline at end of file diff --git a/src/server/server.ts b/src/server/server.ts index 828deca2b2d..d9737a554d0 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -11,7 +11,7 @@ module ts.server { input: process.stdin, output: process.stdout, terminal: false, - }); + }); class Logger implements ts.server.Logger { fd = -1; @@ -170,11 +170,11 @@ module ts.server { removeFile(file: WatchedFile) { this.watchedFiles = WatchedFileSet.copyListRemovingItem(file, this.watchedFiles); } - } + } class IOSession extends Session { - constructor(host: ServerHost, logger: ts.server.Logger) { - super(host, logger); + constructor(host: ServerHost, env: NodeEnvironment, logger: ts.server.Logger) { + super(host, env, logger); } exit() { @@ -265,7 +265,7 @@ module ts.server { } }; - var ioSession = new IOSession(ts.sys, logger); + var ioSession = new IOSession(ts.sys, new NodeEnvironment(), logger); process.on('uncaughtException', function(err: Error) { ioSession.logError(err, "unknown"); }); diff --git a/src/server/session.ts b/src/server/session.ts index a4cb3e59b4e..60ae0b8ee21 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1,6 +1,5 @@ /// /// -/// /// /// @@ -61,7 +60,7 @@ module ts.server { }; } - interface PendingErrorCheck { + export interface PendingErrorCheck { fileName: string; project: Project; } @@ -108,17 +107,32 @@ module ts.server { export interface ServerHost extends ts.System { } + + export interface Environment { + byteLength: (buf: string, encoding?: string) => number; + hrtime: (start?: number[]) => number[]; //array of seconds, nanoseconds + } + + export interface Message { + type: string, + seq: number + } + + export interface Event extends Message { + event: string; + body?: any; + } export class Session { projectService: ProjectService; pendingOperation = false; fileHash: ts.Map = {}; nextFileId = 1; - errorTimer: NodeJS.Timer; + errorTimer: any; /*NodeJS.Timer | number*/ immediateId: any; changeSeq = 0; - constructor(private host: ServerHost, private logger: Logger) { + constructor(private host: ServerHost, private environment: Environment, private logger: Logger) { this.projectService = new ProjectService(host, logger, (eventName,project,fileName) => { this.handleEvent(eventName, project, fileName); @@ -149,17 +163,17 @@ module ts.server { this.host.write(line + this.host.newLine); } - send(msg: NodeJS._debugger.Message) { + send(msg: Message) { var json = JSON.stringify(msg); if (this.logger.isVerbose()) { this.logger.info(msg.type + ": " + json); } - this.sendLineToClient('Content-Length: ' + (1 + Buffer.byteLength(json, 'utf8')) + + this.sendLineToClient('Content-Length: ' + (1 + this.environment.byteLength(json, 'utf8')) + '\r\n\r\n' + json); } event(info: any, eventName: string) { - var ev: NodeJS._debugger.Event = { + var ev: Event = { seq: 0, type: "event", event: eventName, @@ -838,7 +852,7 @@ module ts.server { onMessage(message: string) { if (this.logger.isVerbose()) { this.logger.info("request: " + message); - var start = process.hrtime(); + var start = this.environment.hrtime(); } try { var request = JSON.parse(message); @@ -980,7 +994,7 @@ module ts.server { } if (this.logger.isVerbose()) { - var elapsed = process.hrtime(start); + var elapsed = this.environment.hrtime(start); var seconds = elapsed[0] var nanoseconds = elapsed[1]; var elapsedMs = ((1e9 * seconds) + nanoseconds)/1000000.0; diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json index 2c8538c61e3..bdc0a36cb86 100644 --- a/src/server/tsconfig.json +++ b/src/server/tsconfig.json @@ -12,6 +12,7 @@ "editorServices.ts", "protocol.d.ts", "server.ts", + "nodeimpl.ts", "session.ts" ] } From 85547915743a3bda34117713e75a4c3f390aa1a8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 10 Jun 2015 16:19:10 -0700 Subject: [PATCH 2/4] Decouple ts.sys from the editorServices where possible --- src/server/editorServices.ts | 12 +++++++----- tests/cases/unittests/versionCache.ts | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ffb22cc505b..d31ea53b5f9 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -35,7 +35,7 @@ module ts.server { formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions); constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) { - this.svc = ScriptVersionCache.fromString(content); + this.svc = ScriptVersionCache.fromString(host, content); } setFormatOptions(formatOptions: protocol.FormatOptions): void { @@ -915,7 +915,7 @@ module ts.server { return rawConfig.error; } else { - var parsedCommandLine = ts.parseConfigFile(rawConfig.config, ts.sys, dirPath); + var parsedCommandLine = ts.parseConfigFile(rawConfig.config, this.host, dirPath); if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) { return { errorMsg: "tsconfig option errors" }; } @@ -984,7 +984,7 @@ module ts.server { static defaultFormatCodeOptions: ts.FormatCodeOptions = { IndentSize: 4, TabSize: 4, - NewLineCharacter: ts.sys.newLine, + NewLineCharacter: ts.sys ? ts.sys.newLine : '\n', ConvertTabsToSpaces: true, InsertSpaceAfterCommaDelimiter: true, InsertSpaceAfterSemicolonInForStatements: true, @@ -1262,6 +1262,7 @@ module ts.server { versions: LineIndexSnapshot[] = []; minVersion = 0; // no versions earlier than min version will maintain change history private currentVersion = 0; + private host: System; static changeNumberThreshold = 8; static changeLengthThreshold = 256; @@ -1289,7 +1290,7 @@ module ts.server { } reloadFromFile(filename: string, cb?: () => any) { - var content = ts.sys.readFile(filename); + var content = this.host.readFile(filename); this.reload(content); if (cb) cb(); @@ -1359,10 +1360,11 @@ module ts.server { } } - static fromString(script: string) { + static fromString(host: System, script: string) { var svc = new ScriptVersionCache(); var snap = new LineIndexSnapshot(0, svc); svc.versions[svc.currentVersion] = snap; + svc.host = host; snap.index = new LineIndex(); var lm = LineIndex.linesFromText(script); snap.index.load(lm.lines); diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index 12cf9c1b817..06c2cadbfe9 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -231,7 +231,7 @@ and grew 1cm per day`; }); it("Edit ScriptVersionCache ", () => { - let svc = server.ScriptVersionCache.fromString(testContent); + let svc = server.ScriptVersionCache.fromString(ts.sys, testContent); let checkText = testContent; for (let i = 0; i < iterationCount; i++) { From 7390fe0eab8bd8a081bc7ec92629134d4795f990 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 17 Jun 2015 12:39:02 -0700 Subject: [PATCH 3/4] Feedback form pr #3513 --- Jakefile.js | 6 ++--- src/harness/harnessLanguageService.ts | 2 +- src/server/editorServices.ts | 2 +- src/server/nodeimpl.ts | 7 ------ src/server/server.ts | 6 ++--- src/server/session.ts | 32 +++++++++------------------ 6 files changed, 18 insertions(+), 37 deletions(-) delete mode 100644 src/server/nodeimpl.ts diff --git a/Jakefile.js b/Jakefile.js index 9a2f39ee130..ee0a84987ad 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -100,7 +100,6 @@ var serverSources = [ "editorServices.ts", "protocol.d.ts", "session.ts", - "nodeimpl.ts", "server.ts" ].map(function (f) { return path.join(serverDirectory, f); @@ -112,7 +111,7 @@ var languageServiceLibrarySources = [ "session.ts" ].map(function (f) { return path.join(serverDirectory, f); -}); +}).concat(servicesSources); var harnessSources = [ "harness.ts", @@ -146,7 +145,6 @@ var harnessSources = [ "protocol.d.ts", "session.ts", "client.ts", - "nodeimpl.ts", "editorServices.ts", ].map(function (f) { return path.join(serverDirectory, f); @@ -383,7 +381,7 @@ var lsslFile = path.join(builtLocalDirectory, "tslssl.js"); compileFile( lsslFile, languageServiceLibrarySources, - [builtLocalDirectory, copyright].concat(serverSources).concat(languageServiceLibrarySources), + [builtLocalDirectory, copyright].concat(languageServiceLibrarySources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, /*noOutFile*/ false, diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 3796c84863b..8eb77817533 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -583,7 +583,7 @@ module Harness.LanguageService { // This host is just a proxy for the clientHost, it uses the client // host to answer server queries about files on disk var serverHost = new SessionServerHost(clientHost); - var server = new ts.server.Session(serverHost, new ts.server.NodeEnvironment(), serverHost); + var server = new ts.server.Session(serverHost, Buffer.byteLength, process.hrtime, serverHost); // Fake the connection between the client and the server serverHost.writeMessage = client.onMessage.bind(client); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d31ea53b5f9..53cab79f9af 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1262,7 +1262,7 @@ module ts.server { versions: LineIndexSnapshot[] = []; minVersion = 0; // no versions earlier than min version will maintain change history private currentVersion = 0; - private host: System; + private host: ServerHost; static changeNumberThreshold = 8; static changeLengthThreshold = 256; diff --git a/src/server/nodeimpl.ts b/src/server/nodeimpl.ts deleted file mode 100644 index 9694b49aa85..00000000000 --- a/src/server/nodeimpl.ts +++ /dev/null @@ -1,7 +0,0 @@ -/// -module ts.server { - export class NodeEnvironment implements Environment { - byteLength = Buffer.byteLength; - hrtime = process.hrtime; - } -} \ No newline at end of file diff --git a/src/server/server.ts b/src/server/server.ts index d9737a554d0..e2d195284f5 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -173,8 +173,8 @@ module ts.server { } class IOSession extends Session { - constructor(host: ServerHost, env: NodeEnvironment, logger: ts.server.Logger) { - super(host, env, logger); + constructor(host: ServerHost, logger: ts.server.Logger) { + super(host, Buffer.byteLength, process.hrtime, logger); } exit() { @@ -265,7 +265,7 @@ module ts.server { } }; - var ioSession = new IOSession(ts.sys, new NodeEnvironment(), logger); + var ioSession = new IOSession(ts.sys, logger); process.on('uncaughtException', function(err: Error) { ioSession.logError(err, "unknown"); }); diff --git a/src/server/session.ts b/src/server/session.ts index 60ae0b8ee21..09c6d70a070 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -107,21 +107,6 @@ module ts.server { export interface ServerHost extends ts.System { } - - export interface Environment { - byteLength: (buf: string, encoding?: string) => number; - hrtime: (start?: number[]) => number[]; //array of seconds, nanoseconds - } - - export interface Message { - type: string, - seq: number - } - - export interface Event extends Message { - event: string; - body?: any; - } export class Session { projectService: ProjectService; @@ -132,7 +117,12 @@ module ts.server { immediateId: any; changeSeq = 0; - constructor(private host: ServerHost, private environment: Environment, private logger: Logger) { + constructor( + private host: ServerHost, + private byteLength: (buf: string, encoding?: string) => number, + private hrtime: (start?: number[]) => number[], + private logger: Logger + ) { this.projectService = new ProjectService(host, logger, (eventName,project,fileName) => { this.handleEvent(eventName, project, fileName); @@ -163,17 +153,17 @@ module ts.server { this.host.write(line + this.host.newLine); } - send(msg: Message) { + send(msg: protocol.Message) { var json = JSON.stringify(msg); if (this.logger.isVerbose()) { this.logger.info(msg.type + ": " + json); } - this.sendLineToClient('Content-Length: ' + (1 + this.environment.byteLength(json, 'utf8')) + + this.sendLineToClient('Content-Length: ' + (1 + this.byteLength(json, 'utf8')) + '\r\n\r\n' + json); } event(info: any, eventName: string) { - var ev: Event = { + var ev: protocol.Event = { seq: 0, type: "event", event: eventName, @@ -852,7 +842,7 @@ module ts.server { onMessage(message: string) { if (this.logger.isVerbose()) { this.logger.info("request: " + message); - var start = this.environment.hrtime(); + var start = this.hrtime(); } try { var request = JSON.parse(message); @@ -994,7 +984,7 @@ module ts.server { } if (this.logger.isVerbose()) { - var elapsed = this.environment.hrtime(start); + var elapsed = this.hrtime(start); var seconds = elapsed[0] var nanoseconds = elapsed[1]; var elapsedMs = ((1e9 * seconds) + nanoseconds)/1000000.0; From 9cc97f1fc5777d461e780ac37b30ca366c02f6eb Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 17 Jun 2015 21:17:09 -0700 Subject: [PATCH 4/4] feedback from pr #3542 --- src/server/editorServices.ts | 2 +- src/server/tsconfig.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 53cab79f9af..3cfccaec423 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1360,7 +1360,7 @@ module ts.server { } } - static fromString(host: System, script: string) { + static fromString(host: ServerHost, script: string) { var svc = new ScriptVersionCache(); var snap = new LineIndexSnapshot(0, svc); svc.versions[svc.currentVersion] = snap; diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json index bdc0a36cb86..2c8538c61e3 100644 --- a/src/server/tsconfig.json +++ b/src/server/tsconfig.json @@ -12,7 +12,6 @@ "editorServices.ts", "protocol.d.ts", "server.ts", - "nodeimpl.ts", "session.ts" ] }