diff --git a/src/server/client.ts b/src/server/client.ts
index d51777c2e99..a0b68de840e 100644
--- a/src/server/client.ts
+++ b/src/server/client.ts
@@ -1,5 +1,5 @@
///
-
+
module ts.server {
export interface SessionClientHost extends LanguageServiceHost {
@@ -172,7 +172,7 @@ module ts.server {
documentation: [{ kind: "text", text: response.body.documentation }]
};
}
-
+
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var args: protocol.CompletionsRequestArgs = {
@@ -185,27 +185,28 @@ module ts.server {
var request = this.processRequest(CommandNames.Completions, args);
var response = this.processResponse(request);
- return this.lastCompletionEntry = {
+ return {
isMemberCompletion: false,
isNewIdentifierLocation: false,
- entries: response.body.map(entry => ({
- kind: entry.kind,
- kindModifiers: entry.kindModifiers,
- name: entry.name,
- displayParts: entry.displayParts,
- documentation: entry.documentation
- })),
+ entries: response.body,
fileName: fileName,
position: position
};
}
-
+
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
- if (!this.lastCompletionEntry || this.lastCompletionEntry.fileName !== fileName || this.lastCompletionEntry.position !== position) {
- this.getCompletionsAtPosition(fileName, position);
- }
+ var lineCol = this.positionToOneBasedLineCol(fileName, position);
+ var args: protocol.CompletionDetailsRequestArgs = {
+ file: fileName,
+ line: lineCol.line,
+ col: lineCol.col,
+ entryNames: [entryName]
+ };
- return this.lastCompletionEntry.entries.filter(entry => entry.name === entryName)[0];
+ var request = this.processRequest(CommandNames.CompletionDetails, args);
+ var response = this.processResponse(request);
+ Debug.assert(response.body.length == 1, "Unexpected length of completion details response body.");
+ return response.body[0];
}
getNavigateToItems(searchTerm: string): NavigateToItem[] {
diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts
index a446f0176ae..b07fb20d48d 100644
--- a/src/server/protocol.d.ts
+++ b/src/server/protocol.d.ts
@@ -471,6 +471,26 @@ declare module ts.server.protocol {
arguments: CompletionsRequestArgs;
}
+ /**
+ * Arguments for completion details request.
+ */
+ export interface CompletionDetailsRequestArgs extends FileLocationRequestArgs {
+ /**
+ * Names of one or more entries for which to obtain details.
+ */
+ entryNames: string[];
+ }
+
+ /**
+ * Completion entry details request; value of command field is
+ * "completionEntryDetails". Given a file location (file, line,
+ * col) and an array of completion entry names return more
+ * detailed information for each completion entry.
+ */
+ export interface CompletionDetailsRequest extends FileLocationRequest {
+ arguments: CompletionDetailsRequestArgs;
+ }
+
/**
* Part of a symbol description.
*/
@@ -489,35 +509,42 @@ declare module ts.server.protocol {
/**
* An item found in a completion response.
*/
- export interface CompletionItem {
+ export interface CompletionEntry {
/**
* The symbol's name.
*/
name: string;
-
/**
* The symbol's kind (such as 'className' or 'parameterName').
*/
kind: string;
-
/**
* Optional modifiers for the kind (such as 'public').
*/
- kindModifiers?: string;
-
+ kindModifiers: string;
+ }
+
+ /**
+ * Additional completion entry details, available on demand
+ */
+ export interface CompletionEntryDetails extends CompletionEntry {
/**
* Display parts of the symbol (similar to quick info).
*/
- displayParts?: SymbolDisplayPart[];
+ displayParts: SymbolDisplayPart[];
/**
* Documentation strings for the symbol.
*/
- documentation?: SymbolDisplayPart[];
+ documentation: SymbolDisplayPart[];
}
export interface CompletionsResponse extends Response {
- body?: CompletionItem[];
+ body?: CompletionEntry[];
+ }
+
+ export interface CompletionDetailsResponse extends Response {
+ body?: CompletionEntryDetails[];
}
/**
diff --git a/src/server/session.ts b/src/server/session.ts
index 1a0a8d98a90..bfcf82bce29 100644
--- a/src/server/session.ts
+++ b/src/server/session.ts
@@ -81,7 +81,7 @@ module ts.server {
function formatDiag(fileName: string, project: Project, diag: ts.Diagnostic) {
return {
start: project.compilerService.host.positionToLineCol(fileName, diag.start),
- end: project.compilerService.host.positionToLineCol(fileName, diag.start+diag.length),
+ end: project.compilerService.host.positionToLineCol(fileName, diag.start + diag.length),
text: ts.flattenDiagnosticMessageText(diag.messageText, "\n")
};
}
@@ -104,6 +104,7 @@ module ts.server {
export var Change = "change";
export var Close = "close";
export var Completions = "completions";
+ export var CompletionDetails = "completionEntryDetails";
export var Definition = "definition";
export var Format = "format";
export var Formatonkey = "formatonkey";
@@ -486,8 +487,8 @@ module ts.server {
};
});
}
-
- getCompletions(line: number, col: number, prefix: string, fileName: string): protocol.CompletionItem[] {
+
+ getCompletions(line: number, col: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
if (!prefix) {
prefix = "";
}
@@ -505,27 +506,34 @@ module ts.server {
throw Errors.NoContent;
}
- return completions.entries.reduce((result: ts.CompletionEntryDetails[], entry: ts.CompletionEntry) => {
+ return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
if (completions.isMemberCompletion || entry.name.indexOf(prefix) == 0) {
- var protoEntry = {};
- protoEntry.name = entry.name;
- protoEntry.kind = entry.kind;
- if (entry.kindModifiers && (entry.kindModifiers.length > 0)) {
- protoEntry.kindModifiers = entry.kindModifiers;
- }
- var details = compilerService.languageService.getCompletionEntryDetails(file, position, entry.name);
- if (details && (details.documentation) && (details.documentation.length > 0)) {
- protoEntry.documentation = details.documentation;
- }
- if (details && (details.displayParts) && (details.displayParts.length > 0)) {
- protoEntry.displayParts = details.displayParts;
- }
- result.push(protoEntry);
+ result.push(entry);
}
return result;
}, []);
}
+ getCompletionEntryDetails(line: number, col: number,
+ entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] {
+ var file = ts.normalizePath(fileName);
+ var project = this.projectService.getProjectForFile(file);
+ if (!project) {
+ throw Errors.NoProject;
+ }
+
+ var compilerService = project.compilerService;
+ var position = compilerService.host.lineColToPosition(file, line, col);
+
+ return entryNames.reduce((accum: protocol.CompletionEntryDetails[], entryName: string) => {
+ var details = compilerService.languageService.getCompletionEntryDetails(file, position, entryName);
+ if (details) {
+ accum.push(details);
+ }
+ return accum;
+ }, []);
+ }
+
getDiagnostics(delay: number, fileNames: string[]) {
var checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => {
fileName = ts.normalizePath(fileName);
@@ -724,6 +732,12 @@ module ts.server {
response = this.getCompletions(request.arguments.line, request.arguments.col, completionsArgs.prefix, request.arguments.file);
break;
}
+ case CommandNames.CompletionDetails: {
+ var completionDetailsArgs = request.arguments;
+ response = this.getCompletionEntryDetails(request.arguments.line, request.arguments.col, completionDetailsArgs.entryNames,
+ request.arguments.file);
+ break;
+ }
case CommandNames.Geterr: {
var geterrArgs = request.arguments;
response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files);