mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 20:25:23 -06:00
Merge branch 'tsserverVS-WIP' of https://github.com/Microsoft/TypeScript into tsserverVS-WIP
This commit is contained in:
commit
676ba4f5b1
2
src/server/protocol.d.ts
vendored
2
src/server/protocol.d.ts
vendored
@ -1187,6 +1187,8 @@ declare namespace ts.server.protocol {
|
||||
* Optional limit on the number of items to return.
|
||||
*/
|
||||
maxResultCount?: number;
|
||||
|
||||
projectFileName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -14,12 +14,14 @@ namespace ts.server {
|
||||
});
|
||||
|
||||
class Logger implements ts.server.Logger {
|
||||
fd = -1;
|
||||
seq = 0;
|
||||
inGroup = false;
|
||||
firstInGroup = true;
|
||||
private fd = -1;
|
||||
private seq = 0;
|
||||
private inGroup = false;
|
||||
private firstInGroup = true;
|
||||
|
||||
constructor(public logFilename: string, public level: string) {
|
||||
constructor(private readonly logFilename: string,
|
||||
private readonly traceToConsole: boolean,
|
||||
private readonly level: string) {
|
||||
}
|
||||
|
||||
static padStringRight(str: string, padding: string) {
|
||||
@ -52,7 +54,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
loggingEnabled() {
|
||||
return !!this.logFilename;
|
||||
return !!this.logFilename || this.traceToConsole;
|
||||
}
|
||||
|
||||
isVerbose() {
|
||||
@ -66,7 +68,7 @@ namespace ts.server {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
}
|
||||
if (this.fd >= 0) {
|
||||
if (this.fd >= 0 || this.traceToConsole) {
|
||||
s = s + "\n";
|
||||
const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
|
||||
if (this.firstInGroup) {
|
||||
@ -78,7 +80,13 @@ namespace ts.server {
|
||||
this.firstInGroup = true;
|
||||
}
|
||||
const buf = new Buffer(s);
|
||||
fs.writeSync(this.fd, buf, 0, buf.length, null);
|
||||
if (this.fd >= 0) {
|
||||
fs.writeSync(this.fd, buf, 0, buf.length, null);
|
||||
}
|
||||
if (this.traceToConsole)
|
||||
{
|
||||
console.warn(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -109,6 +117,7 @@ namespace ts.server {
|
||||
interface LogOptions {
|
||||
file?: string;
|
||||
detailLevel?: string;
|
||||
traceToConsole?: boolean;
|
||||
}
|
||||
|
||||
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
|
||||
@ -125,6 +134,9 @@ namespace ts.server {
|
||||
case "-level":
|
||||
logEnv.detailLevel = value;
|
||||
break;
|
||||
case "-traceToConsole":
|
||||
logEnv.traceToConsole = value.toLowerCase() === "true";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -135,6 +147,7 @@ namespace ts.server {
|
||||
function createLoggerFromEnv() {
|
||||
let fileName: string = undefined;
|
||||
let detailLevel = "normal";
|
||||
let traceToConsole = false;
|
||||
const logEnvStr = process.env["TSS_LOG"];
|
||||
if (logEnvStr) {
|
||||
const logEnv = parseLoggingEnvironmentString(logEnvStr);
|
||||
@ -147,8 +160,9 @@ namespace ts.server {
|
||||
if (logEnv.detailLevel) {
|
||||
detailLevel = logEnv.detailLevel;
|
||||
}
|
||||
traceToConsole = logEnv.traceToConsole;
|
||||
}
|
||||
return new Logger(fileName, detailLevel);
|
||||
return new Logger(fileName, traceToConsole, detailLevel);
|
||||
}
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
|
||||
@ -104,9 +104,11 @@ namespace ts.server {
|
||||
export const Change = "change";
|
||||
export const Close = "close";
|
||||
export const Completions = "completions";
|
||||
export const CompletionsFull = "completions-full";
|
||||
export const CompletionDetails = "completionEntryDetails";
|
||||
export const Configure = "configure";
|
||||
export const Definition = "definition";
|
||||
export const DefinitionFull = "definition-full";
|
||||
export const Exit = "exit";
|
||||
export const Format = "format";
|
||||
export const Formatonkey = "formatonkey";
|
||||
@ -116,13 +118,16 @@ namespace ts.server {
|
||||
export const Navto = "navto";
|
||||
export const Occurrences = "occurrences";
|
||||
export const DocumentHighlights = "documentHighlights";
|
||||
export const DocumentHighlightsFull = "documentHighlights-full";
|
||||
export const Open = "open";
|
||||
export const Quickinfo = "quickinfo";
|
||||
export const QuickinfoFull = "quickinfo-full";
|
||||
export const References = "references";
|
||||
export const Reload = "reload";
|
||||
export const Rename = "rename";
|
||||
export const Saveto = "saveto";
|
||||
export const SignatureHelp = "signatureHelp";
|
||||
export const SignatureHelpFull = "signatureHelp-full";
|
||||
export const TypeDefinition = "typeDefinition";
|
||||
export const ProjectInfo = "projectInfo";
|
||||
export const ReloadProjects = "reloadProjects";
|
||||
@ -316,29 +321,34 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
private getDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.FileSpan[] | DefinitionInfo[] {
|
||||
const file = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file);
|
||||
const position = scriptInfo.lineOffsetToPosition(line, offset);
|
||||
const position = this.getPosition(args, scriptInfo);;
|
||||
|
||||
const definitions = project.languageService.getDefinitionAtPosition(file, position);
|
||||
if (!definitions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return definitions.map(def => {
|
||||
const defScriptInfo = project.getScriptInfo(def.fileName);
|
||||
return {
|
||||
file: def.fileName,
|
||||
start: defScriptInfo.positionToLineOffset(def.textSpan.start),
|
||||
end: defScriptInfo.positionToLineOffset(ts.textSpanEnd(def.textSpan))
|
||||
};
|
||||
});
|
||||
if (simplifiedResult) {
|
||||
return definitions.map(def => {
|
||||
const defScriptInfo = project.getScriptInfo(def.fileName);
|
||||
return {
|
||||
file: def.fileName,
|
||||
start: defScriptInfo.positionToLineOffset(def.textSpan.start),
|
||||
end: defScriptInfo.positionToLineOffset(ts.textSpanEnd(def.textSpan))
|
||||
};
|
||||
});
|
||||
}
|
||||
else {
|
||||
return definitions;
|
||||
}
|
||||
}
|
||||
|
||||
private getTypeDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
|
||||
@ -397,8 +407,8 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private getDocumentHighlights(line: number, offset: number, fileName: string, filesToSearch: string[]): protocol.DocumentHighlightsItem[] {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): protocol.DocumentHighlightsItem[] | DocumentHighlights[] {
|
||||
const fileName = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
|
||||
if (!project) {
|
||||
@ -406,15 +416,20 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(fileName);
|
||||
const position = scriptInfo.lineOffsetToPosition(line, offset);
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
|
||||
const documentHighlights = project.languageService.getDocumentHighlights(fileName, position, filesToSearch);
|
||||
const documentHighlights = project.languageService.getDocumentHighlights(fileName, position, args.filesToSearch);
|
||||
|
||||
if (!documentHighlights) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return documentHighlights.map(convertToDocumentHighlightsItem);
|
||||
if (simplifiedResult) {
|
||||
return documentHighlights.map(convertToDocumentHighlightsItem);
|
||||
}
|
||||
else {
|
||||
return documentHighlights;
|
||||
}
|
||||
|
||||
function convertToDocumentHighlightsItem(documentHighlights: ts.DocumentHighlights): ts.server.protocol.DocumentHighlightsItem {
|
||||
const { fileName, highlightSpans } = documentHighlights;
|
||||
@ -608,7 +623,11 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
private getQuickInfo(args: protocol.FileLocationRequestArgs): protocol.QuickInfoResponseBody {
|
||||
private getPosition(args: protocol.FileLocationRequestArgs, scriptInfo: ScriptInfo): number {
|
||||
return args.position !== undefined ? args.position : scriptInfo.lineOffsetToPosition(args.line, args.offset);
|
||||
}
|
||||
|
||||
private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo {
|
||||
const file = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
@ -616,26 +635,26 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file);
|
||||
const position = args.position !== undefined ? args.position : scriptInfo.lineOffsetToPosition(args.line, args.offset);
|
||||
const quickInfo = project.languageService.getQuickInfoAtPosition(file, position);
|
||||
const quickInfo = project.languageService.getQuickInfoAtPosition(file, this.getPosition(args, scriptInfo));
|
||||
if (!quickInfo) {
|
||||
return undefined;
|
||||
}
|
||||
if (args.position !== undefined) {
|
||||
// TODO: fixme
|
||||
return <any>quickInfo;
|
||||
}
|
||||
|
||||
const displayString = ts.displayPartsToString(quickInfo.displayParts);
|
||||
const docString = ts.displayPartsToString(quickInfo.documentation);
|
||||
return {
|
||||
kind: quickInfo.kind,
|
||||
kindModifiers: quickInfo.kindModifiers,
|
||||
start: scriptInfo.positionToLineOffset(quickInfo.textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(ts.textSpanEnd(quickInfo.textSpan)),
|
||||
displayString: displayString,
|
||||
documentation: docString,
|
||||
};
|
||||
if (simplifiedResult) {
|
||||
const displayString = ts.displayPartsToString(quickInfo.displayParts);
|
||||
const docString = ts.displayPartsToString(quickInfo.documentation);
|
||||
return {
|
||||
kind: quickInfo.kind,
|
||||
kindModifiers: quickInfo.kindModifiers,
|
||||
start: scriptInfo.positionToLineOffset(quickInfo.textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(ts.textSpanEnd(quickInfo.textSpan)),
|
||||
displayString: displayString,
|
||||
documentation: docString,
|
||||
};
|
||||
}
|
||||
else {
|
||||
return quickInfo;
|
||||
}
|
||||
}
|
||||
|
||||
private getFormattingEditsForRange(line: number, offset: number, endLine: number, endOffset: number, fileName: string): protocol.CodeEdit[] {
|
||||
@ -736,44 +755,45 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private getCompletions(line: number, offset: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
|
||||
if (!prefix) {
|
||||
prefix = "";
|
||||
}
|
||||
const file = ts.normalizePath(fileName);
|
||||
private getCompletions(args: protocol.CompletionsRequestArgs, simplifiedResult: boolean): protocol.CompletionEntry[] | CompletionInfo {
|
||||
const prefix = args.prefix || "";
|
||||
const file = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file);
|
||||
const position = scriptInfo.lineOffsetToPosition(line, offset);
|
||||
const position = this.getPosition(args, scriptInfo)
|
||||
|
||||
const completions = project.languageService.getCompletionsAtPosition(file, position);
|
||||
if (!completions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
|
||||
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
|
||||
result.push(entry);
|
||||
}
|
||||
return result;
|
||||
}, []).sort((a, b) => a.name.localeCompare(b.name));
|
||||
if (simplifiedResult) {
|
||||
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
|
||||
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
|
||||
result.push(entry);
|
||||
}
|
||||
return result;
|
||||
}, []).sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
else {
|
||||
return completions;
|
||||
}
|
||||
}
|
||||
|
||||
private getCompletionEntryDetails(line: number, offset: number,
|
||||
entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs): protocol.CompletionEntryDetails[] {
|
||||
const file = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file);
|
||||
const position = scriptInfo.lineOffsetToPosition(line, offset);
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
|
||||
return entryNames.reduce((accum: protocol.CompletionEntryDetails[], entryName: string) => {
|
||||
return args.entryNames.reduce((accum: protocol.CompletionEntryDetails[], entryName: string) => {
|
||||
const details = project.languageService.getCompletionEntryDetails(file, position, entryName);
|
||||
if (details) {
|
||||
accum.push(details);
|
||||
@ -782,33 +802,36 @@ namespace ts.server {
|
||||
}, []);
|
||||
}
|
||||
|
||||
private getSignatureHelpItems(line: number, offset: number, fileName: string): protocol.SignatureHelpItems {
|
||||
const file = ts.normalizePath(fileName);
|
||||
private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems {
|
||||
const file = ts.normalizePath(args.file);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file);
|
||||
const position = scriptInfo.lineOffsetToPosition(line, offset);
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
const helpItems = project.languageService.getSignatureHelpItems(file, position);
|
||||
if (!helpItems) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const span = helpItems.applicableSpan;
|
||||
const result: protocol.SignatureHelpItems = {
|
||||
items: helpItems.items,
|
||||
applicableSpan: {
|
||||
start: scriptInfo.positionToLineOffset(span.start),
|
||||
end: scriptInfo.positionToLineOffset(span.start + span.length)
|
||||
},
|
||||
selectedItemIndex: helpItems.selectedItemIndex,
|
||||
argumentIndex: helpItems.argumentIndex,
|
||||
argumentCount: helpItems.argumentCount,
|
||||
};
|
||||
|
||||
return result;
|
||||
if (simplifiedResult) {
|
||||
const span = helpItems.applicableSpan;
|
||||
return {
|
||||
items: helpItems.items,
|
||||
applicableSpan: {
|
||||
start: scriptInfo.positionToLineOffset(span.start),
|
||||
end: scriptInfo.positionToLineOffset(span.start + span.length)
|
||||
},
|
||||
selectedItemIndex: helpItems.selectedItemIndex,
|
||||
argumentIndex: helpItems.argumentIndex,
|
||||
argumentCount: helpItems.argumentCount,
|
||||
};
|
||||
}
|
||||
else {
|
||||
return helpItems;
|
||||
}
|
||||
}
|
||||
|
||||
private getDiagnostics(delay: number, fileNames: string[]) {
|
||||
@ -1075,9 +1098,11 @@ namespace ts.server {
|
||||
this.exit();
|
||||
return this.notRequired();
|
||||
},
|
||||
[CommandNames.Definition]: (request: protocol.Request) => {
|
||||
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return this.requiredResponse(this.getDefinition(defArgs.line, defArgs.offset, defArgs.file));
|
||||
[CommandNames.Definition]: (request: protocol.DefinitionRequest) => {
|
||||
return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.DefinitionFull]: (request: protocol.DefinitionRequest) => {
|
||||
return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.TypeDefinition]: (request: protocol.Request) => {
|
||||
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
@ -1112,7 +1137,10 @@ namespace ts.server {
|
||||
return this.notRequired();
|
||||
},
|
||||
[CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => {
|
||||
return this.requiredResponse(this.getQuickInfo(request.arguments));
|
||||
return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.QuickinfoFull]: (request: protocol.QuickInfoRequest) => {
|
||||
return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.Format]: (request: protocol.Request) => {
|
||||
const formatArgs = <protocol.FormatRequestArgs>request.arguments;
|
||||
@ -1122,20 +1150,20 @@ namespace ts.server {
|
||||
const formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
|
||||
return { response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file), responseRequired: true };
|
||||
},
|
||||
[CommandNames.Completions]: (request: protocol.Request) => {
|
||||
const completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
|
||||
return { response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true };
|
||||
[CommandNames.Completions]: (request: protocol.CompletionDetailsRequest) => {
|
||||
return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.CompletionDetails]: (request: protocol.Request) => {
|
||||
const completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
|
||||
return {
|
||||
response: this.getCompletionEntryDetails(completionDetailsArgs.line, completionDetailsArgs.offset,
|
||||
completionDetailsArgs.entryNames, completionDetailsArgs.file), responseRequired: true
|
||||
};
|
||||
[CommandNames.CompletionsFull]: (request: protocol.CompletionDetailsRequest) => {
|
||||
return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.SignatureHelp]: (request: protocol.Request) => {
|
||||
const signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
|
||||
return { response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true };
|
||||
[CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => {
|
||||
return this.requiredResponse(this.getCompletionEntryDetails(request.arguments))
|
||||
},
|
||||
[CommandNames.SignatureHelp]: (request: protocol.SignatureHelpRequest) => {
|
||||
return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.SignatureHelpFull]: (request: protocol.SignatureHelpRequest) => {
|
||||
return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.Geterr]: (request: protocol.Request) => {
|
||||
const geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
|
||||
@ -1188,9 +1216,11 @@ namespace ts.server {
|
||||
const { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return { response: this.getOccurrences(line, offset, fileName), responseRequired: true };
|
||||
},
|
||||
[CommandNames.DocumentHighlights]: (request: protocol.Request) => {
|
||||
const { line, offset, file: fileName, filesToSearch } = <protocol.DocumentHighlightsRequestArgs>request.arguments;
|
||||
return { response: this.getDocumentHighlights(line, offset, fileName, filesToSearch), responseRequired: true };
|
||||
[CommandNames.DocumentHighlights]: (request: protocol.DocumentHighlightsRequest) => {
|
||||
return this.requiredResponse(this.getDocumentHighlights(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.DocumentHighlightsFull]: (request: protocol.DocumentHighlightsRequest) => {
|
||||
return this.requiredResponse(this.getDocumentHighlights(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.ProjectInfo]: (request: protocol.Request) => {
|
||||
const { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user