From b6905aff0c14face0cb56ed3c0a281f367f563fe Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Apr 2015 22:40:23 -0700 Subject: [PATCH] Add getTypeDefinitionAtPosition to tsserver --- src/server/client.ts | 24 ++++++++++++++- src/server/editorServices.ts | 4 +-- src/server/protocol.d.ts | 15 ++++++++++ src/server/session.ts | 30 ++++++++++++++++++- .../fourslash/server/typedefinition01.ts | 12 ++++++++ 5 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/server/typedefinition01.ts diff --git a/src/server/client.ts b/src/server/client.ts index e4382d93f4f..cebe18ac93a 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -301,7 +301,29 @@ module ts.server { } getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { - throw new Error("Not Implemented Yet."); + var lineOffset = this.positionToOneBasedLineOffset(fileName, position); + var args: protocol.FileLocationRequestArgs = { + file: fileName, + line: lineOffset.line, + offset: lineOffset.offset, + }; + + var request = this.processRequest(CommandNames.Type, args); + var response = this.processResponse(request); + + return response.body.map(entry => { + var fileName = entry.file; + var start = this.lineOffsetToPosition(fileName, entry.start); + var end = this.lineOffsetToPosition(fileName, entry.end); + return { + containerKind: "", + containerName: "", + fileName: fileName, + textSpan: ts.createTextSpanFromBounds(start, end), + kind: "", + name: "" + }; + }); } findReferences(fileName: string, position: number): ReferencedSymbol[]{ diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9ed31c91968..85f0dc14779 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -772,7 +772,7 @@ module ts.server { findConfigFile(searchPath: string): string { while (true) { var fileName = ts.combinePaths(searchPath, "tsconfig.json"); - if (sys.fileExists(fileName)) { + if (this.host.fileExists(fileName)) { return fileName; } var parentPath = ts.getDirectoryPath(searchPath); @@ -922,7 +922,7 @@ module ts.server { var proj = this.createProject(configFilename, projectOptions); for (var i = 0, len = parsedCommandLine.fileNames.length; i < len; i++) { var rootFilename = parsedCommandLine.fileNames[i]; - if (ts.sys.fileExists(rootFilename)) { + if (this.host.fileExists(rootFilename)) { var info = this.openFile(rootFilename, clientFileName == rootFilename); proj.addRoot(info); } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 5bc1ffbe4dc..d781457e5ed 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -125,6 +125,14 @@ declare module ts.server.protocol { export interface DefinitionRequest extends FileLocationRequest { } + /** + * Go to type request; value of command field is + * "type". Return response giving the file locations that + * define the type for the symbol found in file at location line, col. + */ + export interface TypeDefinitionRequest extends FileLocationRequest { + } + /** * Location in source code expressed as (one-based) line and character offset. */ @@ -165,6 +173,13 @@ declare module ts.server.protocol { body?: FileSpan[]; } + /** + * Definition response message. Gives text range for definition. + */ + export interface TypeDefinitionResponse extends Response { + body?: FileSpan[]; + } + /** * Get occurrences request; value of command field is * "occurrences". Return response giving spans that are relevant diff --git a/src/server/session.ts b/src/server/session.ts index 52d33234636..2145a099981 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -97,6 +97,7 @@ module ts.server { export var Rename = "rename"; export var Saveto = "saveto"; export var SignatureHelp = "signatureHelp"; + export var Type = "type"; export var Unknown = "unknown"; } @@ -285,7 +286,29 @@ module ts.server { })); } - getOccurrences(line: number, offset: number, fileName: string): protocol.OccurrencesResponseItem[] { + getTypeDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] { + var file = ts.normalizePath(fileName); + var project = this.projectService.getProjectForFile(file); + if (!project) { + throw Errors.NoProject; + } + + var compilerService = project.compilerService; + var position = compilerService.host.lineOffsetToPosition(file, line, offset); + + var definitions = compilerService.languageService.getTypeDefinitionAtPosition(file, position); + if (!definitions) { + return undefined; + } + + return definitions.map(def => ({ + file: def.fileName, + start: compilerService.host.positionToLineOffset(def.fileName, def.textSpan.start), + end: compilerService.host.positionToLineOffset(def.fileName, ts.textSpanEnd(def.textSpan)) + })); + } + + getOccurrences(line: number, offset: number, fileName: string): protocol.OccurrencesResponseItem[]{ fileName = ts.normalizePath(fileName); let project = this.projectService.getProjectForFile(fileName); @@ -817,6 +840,11 @@ module ts.server { response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file); break; } + case CommandNames.Type: { + 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); diff --git a/tests/cases/fourslash/server/typedefinition01.ts b/tests/cases/fourslash/server/typedefinition01.ts new file mode 100644 index 00000000000..e7c37747aba --- /dev/null +++ b/tests/cases/fourslash/server/typedefinition01.ts @@ -0,0 +1,12 @@ +/// + +// @Filename: b.ts +////import n = require('a'); +////var x/*1*/ = new n.Foo(); + +// @Filename: a.ts +//// /*2*/export class Foo {} + +goTo.marker('1'); +goTo.type(); +verify.caretAtMarker('2'); \ No newline at end of file