diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 443c1c4789c..228b9516de1 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -29,6 +29,9 @@ namespace ts { declare var process: any; declare var global: any; declare var __filename: string; + declare var Buffer: { + new (str: string, encoding ?: string): any; + } declare class Enumerator { public atEnd(): boolean; @@ -267,10 +270,17 @@ namespace ts { args: process.argv.slice(2), newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, - write(s: string): void { + write(s: string): void { + var buffer = new Buffer(s, 'utf8'); + var offset: number = 0; + var toWrite: number = buffer.length; + var written = 0; // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); - }, + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } + }, readFile, writeFile, watchFile: (fileName, callback) => { diff --git a/src/server/session.ts b/src/server/session.ts index 2efe75ee53f..5873958d613 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -884,6 +884,131 @@ namespace ts.server { exit() { } + private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = { + [CommandNames.Exit]: () => { + this.exit(); + return {}; + }, + [CommandNames.Definition]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.TypeDefinition]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.References]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.Rename]: (request: protocol.Request) => { + var renameArgs = request.arguments; + return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)} + }, + [CommandNames.Open]: (request: protocol.Request) => { + var openArgs = request.arguments; + this.openClientFile(openArgs.file); + return {} + }, + [CommandNames.Quickinfo]: (request: protocol.Request) => { + var quickinfoArgs = request.arguments; + return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)}; + }, + [CommandNames.Format]: (request: protocol.Request) => { + var formatArgs = request.arguments; + return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)}; + }, + [CommandNames.Formatonkey]: (request: protocol.Request) => { + var formatOnKeyArgs = request.arguments; + return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)}; + }, + [CommandNames.Completions]: (request: protocol.Request) => { + var completionsArgs = request.arguments; + return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)} + }, + [CommandNames.CompletionDetails]: (request: protocol.Request) => { + var completionDetailsArgs = request.arguments; + return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset, + completionDetailsArgs.entryNames,completionDetailsArgs.file)} + }, + [CommandNames.SignatureHelp]: (request: protocol.Request) => { + var signatureHelpArgs = request.arguments; + return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)} + }, + [CommandNames.Geterr]: (request: protocol.Request) => { + var geterrArgs = request.arguments; + return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false}; + }, + [CommandNames.GeterrForProject]: (request: protocol.Request) => { + let { file, delay } = request.arguments; + return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false}; + }, + [CommandNames.Change]: (request: protocol.Request) => { + var changeArgs = request.arguments; + this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, + changeArgs.insertString, changeArgs.file); + return {responseRequired: false} + }, + [CommandNames.Configure]: (request: protocol.Request) => { + var configureArgs = request.arguments; + this.projectService.setHostConfiguration(configureArgs); + this.output(undefined, CommandNames.Configure, request.seq); + return {responseRequired: false} + }, + [CommandNames.Reload]: (request: protocol.Request) => { + var reloadArgs = request.arguments; + this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); + return {responseRequired: false} + }, + [CommandNames.Saveto]: (request: protocol.Request) => { + var savetoArgs = request.arguments; + this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); + return {responseRequired: false} + }, + [CommandNames.Close]: (request: protocol.Request) => { + var closeArgs = request.arguments; + this.closeClientFile(closeArgs.file); + return {responseRequired: false}; + }, + [CommandNames.Navto]: (request: protocol.Request) => { + var navtoArgs = request.arguments; + return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)}; + }, + [CommandNames.Brace]: (request: protocol.Request) => { + var braceArguments = request.arguments; + return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)}; + }, + [CommandNames.NavBar]: (request: protocol.Request) => { + var navBarArgs = request.arguments; + return {response: this.getNavigationBarItems(navBarArgs.file)}; + }, + [CommandNames.Occurrences]: (request: protocol.Request) => { + var { line, offset, file: fileName } = request.arguments; + return {response: this.getOccurrences(line, offset, fileName)}; + }, + [CommandNames.ProjectInfo]: (request: protocol.Request) => { + var { file, needFileNameList } = request.arguments; + return {response: this.getProjectInfo(file, needFileNameList)}; + }, + }; + addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) { + if (this.handlers[command]) { + throw new Error(`Protocol handler already exists for command "${command}"`); + } + this.handlers[command] = handler; + } + + executeCommand(request: protocol.Request) : {response?: any, responseRequired?: boolean} { + var handler = this.handlers[request.command]; + if (handler) { + return handler(request); + } else { + this.projectService.log("Unrecognized JSON command: " + JSON.stringify(request)); + this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); + return {responseRequired: false}; + } + } + onMessage(message: string) { if (this.logger.isVerbose()) { this.logger.info("request: " + message); @@ -891,149 +1016,7 @@ namespace ts.server { } try { var request = JSON.parse(message); - var response: any; - var errorMessage: string; - var responseRequired = true; - switch (request.command) { - case CommandNames.Exit: { - this.exit(); - responseRequired = false; - break; - } - case CommandNames.Definition: { - var defArgs = request.arguments; - response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.TypeDefinition: { - var defArgs = request.arguments; - response = this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.References: { - var refArgs = request.arguments; - response = this.getReferences(refArgs.line, refArgs.offset, refArgs.file); - break; - } - case CommandNames.Rename: { - var renameArgs = request.arguments; - response = this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings); - break; - } - case CommandNames.Open: { - var openArgs = request.arguments; - this.openClientFile(openArgs.file); - responseRequired = false; - break; - } - case CommandNames.Quickinfo: { - var quickinfoArgs = request.arguments; - response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file); - break; - } - case CommandNames.Format: { - var formatArgs = request.arguments; - response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file); - break; - } - case CommandNames.Formatonkey: { - var formatOnKeyArgs = request.arguments; - response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file); - break; - } - case CommandNames.Completions: { - var completionsArgs = request.arguments; - response = this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file); - break; - } - case CommandNames.CompletionDetails: { - var completionDetailsArgs = request.arguments; - response = - this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset, - completionDetailsArgs.entryNames,completionDetailsArgs.file); - break; - } - case CommandNames.SignatureHelp: { - var signatureHelpArgs = request.arguments; - response = this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file); - break; - } - case CommandNames.Geterr: { - var geterrArgs = request.arguments; - response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files); - responseRequired = false; - break; - } - case CommandNames.GeterrForProject: { - this.logger.info(request.arguments); - let { file, delay } = request.arguments; - response = this.getDiagnosticsForProject(delay, file); - responseRequired = false; - break; - } - case CommandNames.Change: { - var changeArgs = request.arguments; - this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, - changeArgs.insertString, changeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Configure: { - var configureArgs = request.arguments; - this.projectService.setHostConfiguration(configureArgs); - this.output(undefined, CommandNames.Configure, request.seq); - responseRequired = false; - break; - } - case CommandNames.Reload: { - var reloadArgs = request.arguments; - this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); - responseRequired = false; - break; - } - case CommandNames.Saveto: { - var savetoArgs = request.arguments; - this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); - responseRequired = false; - break; - } - case CommandNames.Close: { - var closeArgs = request.arguments; - this.closeClientFile(closeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Navto: { - var navtoArgs = request.arguments; - response = this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount); - break; - } - case CommandNames.Brace: { - var braceArguments = request.arguments; - response = this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file); - break; - } - case CommandNames.NavBar: { - var navBarArgs = request.arguments; - response = this.getNavigationBarItems(navBarArgs.file); - break; - } - case CommandNames.Occurrences: { - var { line, offset, file: fileName } = request.arguments; - response = this.getOccurrences(line, offset, fileName); - break; - } - case CommandNames.ProjectInfo: { - var { file, needFileNameList } = request.arguments; - response = this.getProjectInfo(file, needFileNameList); - break; - } - default: { - this.projectService.log("Unrecognized JSON command: " + message); - this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); - break; - } - } + var {response, responseRequired} = this.executeCommand(request); if (this.logger.isVerbose()) { var elapsed = this.hrtime(start); diff --git a/src/services/services.ts b/src/services/services.ts index 10e38f98613..c85c10dc411 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4546,6 +4546,7 @@ namespace ts { if (hasKind(node.parent, SyntaxKind.GetAccessor) || hasKind(node.parent, SyntaxKind.SetAccessor)) { return getGetAndSetOccurrences(node.parent); } + break; default: if (isModifier(node.kind) && node.parent && (isDeclaration(node.parent) || node.parent.kind === SyntaxKind.VariableStatement)) {