diff --git a/src/server/client.ts b/src/server/client.ts index 875e3ffdb5b..60421421780 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -433,7 +433,35 @@ module ts.server { } getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { - throw new Error("Not Implemented Yet."); + var lineOffset = this.positionToOneBasedLineOffset(fileName, position); + var args: protocol.SignatureHelpRequestArgs = { + file: fileName, + line: lineOffset.line, + offset: lineOffset.offset + }; + + var request = this.processRequest(CommandNames.SignatureHelp, args); + var response = this.processResponse(request); + + if (!response.body) { + return undefined; + } + var helpItems: protocol.SignatureHelpItems = response.body; + var span = helpItems.applicableSpan; + var start = this.lineOffsetToPosition(fileName, span.start); + var end = this.lineOffsetToPosition(fileName, span.end); + + var result: SignatureHelpItems = { + items: helpItems.items, + applicableSpan: { + start: start, + length: end - start + }, + selectedItemIndex: helpItems.selectedItemIndex, + argumentIndex: helpItems.argumentIndex, + argumentCount: helpItems.argumentCount, + } + return result; } getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] { diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index d63aa53ba12..cad008c3a73 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -592,6 +592,122 @@ declare module ts.server.protocol { body?: CompletionEntryDetails[]; } + /** + * Signature help information for a single parameter + */ + export interface SignatureHelpParameter { + + /** + * The parameter's name + */ + name: string; + + /** + * Documentation of the parameter. + */ + documentation: SymbolDisplayPart[]; + + /** + * Display parts of the parameter. + */ + displayParts: SymbolDisplayPart[]; + + /** + * Whether the parameter is optional or not. + */ + isOptional: boolean; + } + + /** + * Represents a single signature to show in signature help. + */ + export interface SignatureHelpItem { + + /** + * Whether the signature accepts a variable number of arguments. + */ + isVariadic: boolean; + + /** + * The prefix display parts. + */ + prefixDisplayParts: SymbolDisplayPart[]; + + /** + * The suffix disaply parts. + */ + suffixDisplayParts: SymbolDisplayPart[]; + + /** + * The separator display parts. + */ + separatorDisplayParts: SymbolDisplayPart[]; + + /** + * The signature helps items for the parameters. + */ + parameters: SignatureHelpParameter[]; + + /** + * The signature's documentation + */ + documentation: SymbolDisplayPart[]; + } + + /** + * Signature help items found in the response of a signature help request. + */ + export interface SignatureHelpItems { + + /** + * The signature help items. + */ + items: SignatureHelpItem[]; + + /** + * The span for which signature help should appear on a signature + */ + applicableSpan: TextSpan; + + /** + * The item selected in the set of available help items. + */ + selectedItemIndex: number; + + /** + * The argument selected in the set of parameters. + */ + argumentIndex: number; + + /** + * The argument count + */ + argumentCount: number; + } + + /** + * Arguments of a signature help request. + */ + export interface SignatureHelpRequestArgs extends FileLocationRequestArgs { + + } + + /** + * Signature help request; value of command field is "signatureHelp". + * Given a file location (file, line, col), return the signature + * help. + */ + export interface SignatureHelpRequest extends FileLocationRequest { + arguments: SignatureHelpRequestArgs; + } + + /** + * Repsonse object for a SignatureHelpRequest. + */ + export interface SignatureHelpResponse extends Response { + body?: SignatureHelpItems; + } + /** * Arguments for geterr messages. */ diff --git a/src/server/session.ts b/src/server/session.ts index 47ef40a8809..70d301d8ecc 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -80,6 +80,7 @@ module ts.server { export var Close = "close"; export var Completions = "completions"; export var CompletionDetails = "completionEntryDetails"; + export var SignatureHelp = "signatureHelp"; export var Configure = "configure"; export var Definition = "definition"; export var Format = "format"; @@ -577,6 +578,35 @@ module ts.server { }, []); } + getSignatureHelpItems(line: number, offset: number, fileName: string): protocol.SignatureHelpItems { + 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 helpItems = compilerService.languageService.getSignatureHelpItems(file, position); + if (!helpItems) { + return undefined; + } + + var span = helpItems.applicableSpan; + var result: protocol.SignatureHelpItems = { + items: helpItems.items, + applicableSpan: { + start: compilerService.host.positionToLineOffset(file, span.start), + end: compilerService.host.positionToLineOffset(file, span.start + span.length) + }, + selectedItemIndex: helpItems.selectedItemIndex, + argumentIndex: helpItems.argumentIndex, + argumentCount: helpItems.argumentCount, + } + + return result; + } + getDiagnostics(delay: number, fileNames: string[]) { var checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => { fileName = ts.normalizePath(fileName); @@ -790,6 +820,11 @@ module ts.server { 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); diff --git a/tests/cases/fourslash/server/signatureHelp.ts b/tests/cases/fourslash/server/signatureHelp.ts new file mode 100644 index 00000000000..294df367f07 --- /dev/null +++ b/tests/cases/fourslash/server/signatureHelp.ts @@ -0,0 +1,16 @@ +/// + +////function foo(data: number) { +////} +//// +////function bar { +//// foo(/*1*/) +////} + +goTo.marker('1'); +verify.signatureHelpPresent(); +verify.signatureHelpCountIs(1); +verify.signatureHelpArgumentCountIs(0); + +verify.currentSignatureParameterCountIs(1); +verify.currentSignatureHelpDocCommentIs(''); \ No newline at end of file