Recover from git corruption
This commit is contained in:
parent
99373dbd89
commit
a0b557e1e2
|
@ -128,7 +128,9 @@ module Harness.LanguageService {
|
||||||
protected settings = ts.getDefaultCompilerOptions()) {
|
protected settings = ts.getDefaultCompilerOptions()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getNewLine(): string {
return "\r\n";
}
|
public getNewLine(): string {
|
||||||
|
return "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
public getFilenames(): string[] {
|
public getFilenames(): string[] {
|
||||||
var fileNames: string[] = [];
|
var fileNames: string[] = [];
|
||||||
|
@ -435,17 +437,26 @@ module Harness.LanguageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server adapter
|
// Server adapter
|
||||||
class ServerLanguageServiceHost extends NativeLanguageServiceHost {
|
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
|
||||||
private client: ts.server.SessionClient;
|
private client: ts.server.SessionClient;
|
||||||
|
|
||||||
constructor(cancellationToken: ts.CancellationToken, settings: ts.CompilerOptions) {
|
constructor(cancellationToken: ts.CancellationToken, settings: ts.CompilerOptions) {
|
||||||
super(cancellationToken, settings);
|
super(cancellationToken, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
setClient(client: ts.server.SessionClient) {
|
onMessage(message: string): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
writeMessage(message: string): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setClient(client: ts.server.SessionClient) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
openFile(fileName: string): void {
|
openFile(fileName: string): void {
|
||||||
super.openFile(fileName);
|
super.openFile(fileName);
|
||||||
this.client.openFile(fileName);
|
this.client.openFile(fileName);
|
||||||
}
|
}
|
||||||
|
@ -456,15 +467,135 @@ module Harness.LanguageService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SessionServerHost implements ts.server.ServerHost, ts.server.Logger {
|
||||||
|
args: string[] = [];
|
||||||
|
newLine: string;
|
||||||
|
useCaseSensitiveFileNames: boolean = false;
|
||||||
|
|
||||||
|
constructor(private host: NativeLanguageServiceHost) {
|
||||||
|
this.newLine = this.host.getNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(message: string): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
writeMessage(message: string): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
write(message: string): void {
|
||||||
|
this.writeMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
readFile(fileName: string): string {
|
||||||
|
var snapshot = this.host.getScriptSnapshot(fileName);
|
||||||
|
return snapshot && snapshot.getText(0, snapshot.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFile(name: string, text: string, writeByteOrderMark: boolean): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvePath(path: string): string {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileExists(path: string): boolean {
|
||||||
|
return !!this.host.getScriptSnapshot(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryExists(path: string): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getExecutingFilePath(): string {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(exitCode: number): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
createDirectory(directoryName: string): void {
|
||||||
|
throw new Error("Not Implemented Yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentDirectory(): string {
|
||||||
|
return this.host.getCurrentDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
readDirectory(path: string, extension?: string): string[] {
|
||||||
|
throw new Error("Not implemented Yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
getModififedTime(fileName: string): Date {
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
stat(path: string, callback?: (err: any, stats: any) => any) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineColToPosition(fileName: string, line: number, col: number): number {
|
||||||
|
return this.host.lineColToPosition(fileName, line, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter {
|
||||||
|
return this.host.positionToZeroBasedLineCol(fileName, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileLength(fileName: string): number {
|
||||||
|
return this.host.getScriptSnapshot(fileName).getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileNames(): string[] {
|
||||||
|
return this.host.getScriptFileNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
info(message: string): void {
|
||||||
|
return this.host.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg(message: string) {
|
||||||
|
return this.host.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
endGroup(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
perftrc(message: string): void {
|
||||||
|
return this.host.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
startGroup(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class ServerLanugageServiceAdapter implements LanguageServiceAdapter {
|
export class ServerLanugageServiceAdapter implements LanguageServiceAdapter {
|
||||||
private host: ServerLanguageServiceHost;
|
private host: SessionClientHost;
|
||||||
private client: ts.server.SessionClient;
|
private client: ts.server.SessionClient;
|
||||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||||
debugger;
|
// This is the main host that tests use to direct tests
|
||||||
|
var clientHost = new SessionClientHost(cancellationToken, options);
|
||||||
|
var client = new ts.server.SessionClient(clientHost);
|
||||||
|
|
||||||
this.host = new ServerLanguageServiceHost(cancellationToken, options);
|
// This host is just a proxy for the clientHost, it uses the client
|
||||||
this.client = new ts.server.SessionClient(this.host, /*abbreviate*/ true);
|
// host to answer server queries about files on disk
|
||||||
this.host.setClient(this.client);
|
var serverHost = new SessionServerHost(clientHost);
|
||||||
|
var server = new ts.server.Session(serverHost, serverHost, /*useProtocol*/ true, /*prettyJSON*/ false);
|
||||||
|
|
||||||
|
// Fake the connection between the client and the server
|
||||||
|
serverHost.writeMessage = client.onMessage.bind(client);
|
||||||
|
clientHost.writeMessage = server.onMessage.bind(server);
|
||||||
|
|
||||||
|
// Wire the client to the host to get notifications when a file is open
|
||||||
|
// or edited.
|
||||||
|
clientHost.setClient(client);
|
||||||
|
|
||||||
|
// Set the properties
|
||||||
|
this.client = client;
|
||||||
|
this.host = clientHost;
|
||||||
}
|
}
|
||||||
getHost() { return this.host; }
|
getHost() { return this.host; }
|
||||||
getLanguageService(): ts.LanguageService { return this.client; }
|
getLanguageService(): ts.LanguageService { return this.client; }
|
||||||
|
|
|
@ -1,177 +1,49 @@
|
||||||
/// <reference path="protocol.ts" />
|
/// <reference path="protocol.ts" />
|
||||||
|
|
||||||
module ts.server {
|
|
||||||
|
|
||||||
export interface SessionClientHost extends LanguageServiceHost {
|
|
||||||
lineColToPosition(fileName: string, line: number, col: number): number;
|
|
||||||
positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SessionClientHostProxy implements ServerHost, Logger {
|
|
||||||
args: string[] = [];
|
|
||||||
newLine: string;
|
|
||||||
useCaseSensitiveFileNames: boolean = false;
|
|
||||||
lastReply: string;
|
|
||||||
|
|
||||||
constructor(private host: SessionClientHost) {
|
|
||||||
this.newLine = this.host.getNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
write(message: string): void {
|
module ts.server {
|
||||||
this.lastReply = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
readFile(fileName: string): string {
|
export interface SessionClientHost extends LanguageServiceHost {
|
||||||
var snapshot = this.host.getScriptSnapshot(fileName);
|
writeMessage(message: string): void;
|
||||||
return snapshot && snapshot.getText(0, snapshot.getLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFile(name: string, text:string, writeByteOrderMark: boolean): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvePath(path: string): string {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
fileExists(path: string): boolean {
|
|
||||||
return !!this.host.getScriptSnapshot(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
directoryExists(path: string): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getExecutingFilePath(): string {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(exitCode: number): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
createDirectory(directoryName: string): void {
|
|
||||||
throw new Error("Not Implemented Yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentDirectory(): string {
|
|
||||||
return this.host.getCurrentDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
readDirectory(path: string, extension?: string): string[] {
|
|
||||||
throw new Error("Not implemented Yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
getModififedTime(fileName: string): Date {
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
stat(path: string, callback?: (err: any, stats: any) => any) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lineColToPosition(fileName: string, line: number, col: number): number {
|
|
||||||
return this.host.lineColToPosition(fileName, line, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter {
|
|
||||||
return this.host.positionToZeroBasedLineCol(fileName, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileLength(fileName: string): number {
|
|
||||||
return this.host.getScriptSnapshot(fileName).getLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileNames(): string[] {
|
|
||||||
return this.host.getScriptFileNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
close(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
info(message: string): void {
|
|
||||||
return this.host.log(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg(message: string) {
|
|
||||||
return this.host.log(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
endGroup(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
perftrc(message: string): void {
|
|
||||||
return this.host.log(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
startGroup(): void {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SessionClient implements LanguageService {
|
|
||||||
private session: Session;
|
|
||||||
private sequence: number = 0;
|
|
||||||
private host: SessionClientHostProxy;
|
|
||||||
private expantionTable: ts.Map<string>;
|
|
||||||
private fileMapping: ts.Map<string> = {};
|
|
||||||
|
|
||||||
constructor(host: SessionClientHost, abbreviate: boolean) {
|
|
||||||
this.sequence = 0;
|
|
||||||
this.host = new SessionClientHostProxy(host);
|
|
||||||
this.session = new Session(this.host, this.host, /* useProtocol */ true, /*prettyJSON*/ false);
|
|
||||||
|
|
||||||
// Setup the abbreviation table
|
|
||||||
if (abbreviate) {
|
|
||||||
this.setupExpantionTable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private setupExpantionTable(): void {
|
|
||||||
var request = this.processRequest<ServerProtocol.AbbrevRequest>(CommandNames.Abbrev);
|
|
||||||
var response = this.processResponse<ServerProtocol.AbbrevResponse>(request);
|
|
||||||
var abbriviationTable = response.body;
|
|
||||||
|
|
||||||
Debug.assert(!!abbriviationTable, "Could not setup abbreviation. Abbreviation table was empty.");
|
export class SessionClient implements LanguageService {
|
||||||
|
private sequence: number = 0;
|
||||||
var expantionTable: ts.Map<string> = {};
|
private fileMapping: ts.Map<string> = {};
|
||||||
for (var p in abbriviationTable) {
|
private lineMaps: ts.Map<number[]> = {};
|
||||||
if (abbriviationTable.hasOwnProperty(p)) {
|
private messages: string[] = [];
|
||||||
expantionTable[abbriviationTable[p]] = p;
|
|
||||||
}
|
constructor(private host: SessionClientHost) {
|
||||||
}
|
|
||||||
this.expantionTable = expantionTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private expand<T>(obj: T): T {
|
|
||||||
for (var p in obj) {
|
|
||||||
if (obj.hasOwnProperty(p)) {
|
|
||||||
if (typeof (<any>obj)[p] === "object") {
|
|
||||||
// Expand the property value
|
|
||||||
(<any>obj)[p] = this.expand((<any>obj)[p]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Substitute the name if applicaple
|
|
||||||
var substitution = ts.lookUp(this.expantionTable, p);
|
|
||||||
if (substitution) {
|
|
||||||
(<any>obj)[substitution] = (<any>obj)[p];
|
|
||||||
(<any>obj)[p] = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
private lineColToPosition(fileName: string, lineCol: ServerProtocol.LineCol): number {
|
|
||||||
return this.host.lineColToPosition(fileName, lineCol.line, lineCol.col);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private positionToOneBasedLineCol(fileName: string, position: number): ServerProtocol.LineCol {
|
public onMessage(message: string): void {
|
||||||
var lineCol = this.host.positionToZeroBasedLineCol(fileName, position);
|
this.messages.push(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private writeMessage(message: string): void {
|
||||||
|
this.host.writeMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getLineMap(fileName: string): number[] {
|
||||||
|
var lineMap = ts.lookUp(this.lineMaps, fileName);
|
||||||
|
if (!lineMap) {
|
||||||
|
var scriptSnapshot = this.host.getScriptSnapshot(fileName);
|
||||||
|
lineMap = this.lineMaps[fileName] = ts.computeLineStarts(scriptSnapshot.getText(0, scriptSnapshot.getLength()));
|
||||||
|
}
|
||||||
|
return lineMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private lineColToPosition(fileName: string, lineCol: ServerProtocol.LineCol): number {
|
||||||
|
return ts.computePositionFromLineAndCharacter(this.getLineMap(fileName), lineCol.line, lineCol.col);
|
||||||
|
}
|
||||||
|
|
||||||
|
private positionToOneBasedLineCol(fileName: string, position: number): ServerProtocol.LineCol {
|
||||||
|
var lineCol = ts.computeLineAndCharacterOfPosition(this.getLineMap(fileName), position);
|
||||||
return {
|
return {
|
||||||
line: lineCol.line + 1,
|
line: lineCol.line,
|
||||||
col: lineCol.character + 1
|
col: lineCol.character
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertCodeEditsToTextChange(fileName: string, codeEdit: ServerProtocol.CodeEdit): ts.TextChange {
|
private convertCodeEditsToTextChange(fileName: string, codeEdit: ServerProtocol.CodeEdit): ts.TextChange {
|
||||||
var start = this.lineColToPosition(fileName, codeEdit.start);
|
var start = this.lineColToPosition(fileName, codeEdit.start);
|
||||||
var end = this.lineColToPosition(fileName, codeEdit.end);
|
var end = this.lineColToPosition(fileName, codeEdit.end);
|
||||||
|
@ -180,8 +52,8 @@ module ts.server {
|
||||||
span: ts.createTextSpanFromBounds(start, end),
|
span: ts.createTextSpanFromBounds(start, end),
|
||||||
newText: codeEdit.newText
|
newText: codeEdit.newText
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFileNameFromEncodedFile(fileId: ServerProtocol.EncodedFile): string {
|
private getFileNameFromEncodedFile(fileId: ServerProtocol.EncodedFile): string {
|
||||||
var fileName: string;
|
var fileName: string;
|
||||||
if (typeof fileId === "object") {
|
if (typeof fileId === "object") {
|
||||||
|
@ -196,9 +68,9 @@ module ts.server {
|
||||||
Debug.fail("Got unexpedted fileId type.");
|
Debug.fail("Got unexpedted fileId type.");
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private processRequest<T extends ServerProtocol.Request>(command: string, arguments?: any): T {
|
private processRequest<T extends ServerProtocol.Request>(command: string, arguments?: any): T {
|
||||||
var request: ServerProtocol.Request = {
|
var request: ServerProtocol.Request = {
|
||||||
seq: this.sequence++,
|
seq: this.sequence++,
|
||||||
type: "request",
|
type: "request",
|
||||||
|
@ -206,34 +78,33 @@ module ts.server {
|
||||||
arguments: arguments
|
arguments: arguments
|
||||||
};
|
};
|
||||||
|
|
||||||
this.session.executeJSONcmd(JSON.stringify(request));
|
this.writeMessage(JSON.stringify(request));
|
||||||
|
|
||||||
return <T>request;
|
return <T>request;
|
||||||
}
|
}
|
||||||
|
|
||||||
private processResponse<T extends ServerProtocol.Response>(request: ServerProtocol.Request): T {
|
private processResponse<T extends ServerProtocol.Response>(request: ServerProtocol.Request): T {
|
||||||
debugger;
|
debugger;
|
||||||
|
|
||||||
var lastMessage = this.host.lastReply;
|
var lastMessage = this.messages.shift();
|
||||||
this.host.lastReply = undefined;
|
Debug.assert(!!lastMessage, "Did not recieve any responses.");
|
||||||
Debug.assert(!!lastMessage, "Did not recieve any responses.");
|
|
||||||
|
// Read the content length
|
||||||
// Read the content length
|
var contentLengthPrefix = "Content-Length: ";
|
||||||
var contentLengthPrefix = "Content-Length: ";
|
var lines = lastMessage.split("\r\n");
|
||||||
var lines = lastMessage.split("\r\n");
|
Debug.assert(lines.length >= 2, "Malformed response: Expected 3 lines in the response.");
|
||||||
Debug.assert(lines.length >= 2, "Malformed response: Expected 3 lines in the response.");
|
|
||||||
|
var contentLengthText = lines[0];
|
||||||
var contentLengthText = lines[0];
|
Debug.assert(contentLengthText.indexOf(contentLengthPrefix) === 0, "Malformed response: Response text did not contain content-length header.");
|
||||||
Debug.assert(contentLengthText.indexOf(contentLengthPrefix) === 0, "Malformed response: Response text did not contain content-length header.");
|
var contentLength = parseInt(contentLengthText.substring(contentLengthPrefix.length));
|
||||||
var contentLength = parseInt(contentLengthText.substring(contentLengthPrefix.length));
|
|
||||||
|
// Read the body
|
||||||
// Read the body
|
var responseBody = lines[2];
|
||||||
var responseBody = lines[2];
|
|
||||||
|
// Verify content length
|
||||||
// Verify content length
|
Debug.assert(responseBody.length + 1 === contentLength, "Malformed response: Content length did not match the response's body length.");
|
||||||
Debug.assert(responseBody.length + 1 === contentLength, "Malformed response: Content length did not match the response's body length.");
|
|
||||||
|
try {
|
||||||
try {
|
|
||||||
var response: T = JSON.parse(responseBody);
|
var response: T = JSON.parse(responseBody);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
@ -250,13 +121,9 @@ module ts.server {
|
||||||
|
|
||||||
Debug.assert(!!response.body, "Malformed response: Unexpected empty response body.");
|
Debug.assert(!!response.body, "Malformed response: Unexpected empty response body.");
|
||||||
|
|
||||||
if (this.expantionTable) {
|
|
||||||
// Expand the response if abbreviated
|
|
||||||
return this.expand(response);
|
|
||||||
}
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
openFile(fileName: string): void {
|
openFile(fileName: string): void {
|
||||||
var args: ServerProtocol.FileRequestArgs = { file: fileName };
|
var args: ServerProtocol.FileRequestArgs = { file: fileName };
|
||||||
this.processRequest(CommandNames.Open, args);
|
this.processRequest(CommandNames.Open, args);
|
||||||
|
@ -268,6 +135,9 @@ module ts.server {
|
||||||
}
|
}
|
||||||
|
|
||||||
changeFile(fileName: string, start: number, end: number, newText: string): void {
|
changeFile(fileName: string, start: number, end: number, newText: string): void {
|
||||||
|
// clear the line map after an edit
|
||||||
|
this.lineMaps[fileName] = undefined;
|
||||||
|
|
||||||
var lineCol = this.positionToOneBasedLineCol(fileName, start);
|
var lineCol = this.positionToOneBasedLineCol(fileName, start);
|
||||||
var args: ServerProtocol.ChangeRequestArgs = {
|
var args: ServerProtocol.ChangeRequestArgs = {
|
||||||
file: fileName,
|
file: fileName,
|
||||||
|
@ -326,7 +196,7 @@ module ts.server {
|
||||||
getNavigateToItems(searchTerm: string): NavigateToItem[] {
|
getNavigateToItems(searchTerm: string): NavigateToItem[] {
|
||||||
var args: ServerProtocol.NavtoRequestArgs = {
|
var args: ServerProtocol.NavtoRequestArgs = {
|
||||||
searchTerm,
|
searchTerm,
|
||||||
file: this.host.getFileNames()[0]
|
file: this.host.getScriptFileNames()[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
var request = this.processRequest<ServerProtocol.NavtoRequest>(CommandNames.Navto, args);
|
var request = this.processRequest<ServerProtocol.NavtoRequest>(CommandNames.Navto, args);
|
||||||
|
@ -357,7 +227,7 @@ module ts.server {
|
||||||
file: fileName,
|
file: fileName,
|
||||||
line: startLineCol.line,
|
line: startLineCol.line,
|
||||||
col: startLineCol.col,
|
col: startLineCol.col,
|
||||||
endLine: endLineCol.line,
|
endLine: endLineCol.line,
|
||||||
endCol: endLineCol.col,
|
endCol: endLineCol.col,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -369,7 +239,7 @@ module ts.server {
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): ts.TextChange[] {
|
getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): ts.TextChange[] {
|
||||||
return this.getFormattingEditsForRange(fileName, 0, this.host.getFileLength(fileName), options);
|
return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName).getLength(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): ts.TextChange[] {
|
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): ts.TextChange[] {
|
||||||
|
@ -537,7 +407,7 @@ module ts.server {
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
throw new Error("dispose is not available through the server layer.");
|
throw new Error("dispose is not available through the server layer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,7 +425,8 @@ module ts.server {
|
||||||
if (projectOptions.compilerOptions) {
|
if (projectOptions.compilerOptions) {
|
||||||
this.compilerService.setCompilerOptions(projectOptions.compilerOptions);
|
this.compilerService.setCompilerOptions(projectOptions.compilerOptions);
|
||||||
}
|
}
|
||||||
// TODO: format code options
}
|
// TODO: format code options
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectOpenResult {
|
export interface ProjectOpenResult {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
56
src/server/protodef.d.ts
vendored
56
src/server/protodef.d.ts
vendored
|
@ -188,18 +188,6 @@ declare module ServerProtocol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Type request; value of command field is "type". Return response
|
|
||||||
giving the code locations that define the type of the symbol
|
|
||||||
found in file at location line, col.
|
|
||||||
*/
|
|
||||||
export interface TypeRequest extends CodeLocationRequest {
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TypeResponse extends Response {
|
|
||||||
body?: CodeSpan[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Open request; value of command field is "open". Notify the
|
Open request; value of command field is "open". Notify the
|
||||||
server that the client has file open. The server will not
|
server that the client has file open. The server will not
|
||||||
|
@ -483,8 +471,8 @@ declare module ServerProtocol {
|
||||||
kindModifiers?: string;
|
kindModifiers?: string;
|
||||||
/**
|
/**
|
||||||
The file in which the symbol is found; the value of this
|
The file in which the symbol is found; the value of this
|
||||||
field will always be a string unless the client opts-in to
|
field will always be a string, number of a mapping between
|
||||||
file encoding by sending the "abbrev" request.
|
a string and a number.
|
||||||
*/
|
*/
|
||||||
file: EncodedFile;
|
file: EncodedFile;
|
||||||
/** The location within file at which the symbol is found*/
|
/** The location within file at which the symbol is found*/
|
||||||
|
@ -528,27 +516,6 @@ declare module ServerProtocol {
|
||||||
arguments: ChangeRequestArgs;
|
arguments: ChangeRequestArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
The following messages describe an OPTIONAL compression scheme
|
|
||||||
that clients can choose to use. If a client does not opt-in to
|
|
||||||
this scheme by sending an "abbrev" request, the server will not
|
|
||||||
compress messages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
Abbrev request message; value of command field is "abbrev".
|
|
||||||
Server returns an array of mappings from common message field
|
|
||||||
names and common message field string values to shortened
|
|
||||||
versions of these strings. Once a client opts-in by requesting
|
|
||||||
the abbreviations, the server may send responses whose field
|
|
||||||
names are shortened. The server may also send file names as
|
|
||||||
instances of AssignFileId, or as file ids, if the corresponding
|
|
||||||
id assignment had been previously returned. Currently, only
|
|
||||||
responses to the "navto" request can be encoded.
|
|
||||||
*/
|
|
||||||
export interface AbbrevRequest extends Request {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If an object of this type is returned in place of a string as
|
If an object of this type is returned in place of a string as
|
||||||
the value of a file field in a response message, add the
|
the value of a file field in a response message, add the
|
||||||
|
@ -572,25 +539,6 @@ declare module ServerProtocol {
|
||||||
*/
|
*/
|
||||||
export type EncodedFile = number | IdFile | string;
|
export type EncodedFile = number | IdFile | string;
|
||||||
|
|
||||||
/**
|
|
||||||
Response to abbrev opt-in request message. This is a map of
|
|
||||||
string field names and common string field values to shortened
|
|
||||||
strings. Once the server sends this response, it will assume
|
|
||||||
that it can use the shortened field names and field values. In
|
|
||||||
addition, the server will assume it can assign ids to file
|
|
||||||
names by returning an AssignFileId instance in place of a file
|
|
||||||
name. Once an AssignFileId instance is returned, the server
|
|
||||||
may send the file id (a number) in place of the file name.
|
|
||||||
*/
|
|
||||||
export interface AbbrevResponse extends Response {
|
|
||||||
body?: {
|
|
||||||
/** Map from full string (either field name or string
|
|
||||||
field value) to shortened string */
|
|
||||||
[fullString: string]: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Response to "brace" request. */
|
/** Response to "brace" request. */
|
||||||
export interface BraceResponse extends Response {
|
export interface BraceResponse extends Response {
|
||||||
body?: TextSpan[];
|
body?: TextSpan[];
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/// <reference path="node.d.ts" />
|
/// <reference path="node.d.ts" />
|
||||||
/// <reference path="protocol.ts" />
|
/// <reference path="protocol.ts" />
|
||||||
|
|
||||||
module ts.server {
|
module ts.server {
|
||||||
var nodeproto: typeof NodeJS._debugger = require('_debugger');
|
var nodeproto: typeof NodeJS._debugger = require('_debugger');
|
||||||
var readline: NodeJS.ReadLine = require('readline');
|
var readline: NodeJS.ReadLine = require('readline');
|
||||||
var path: NodeJS.Path = require('path');
|
var path: NodeJS.Path = require('path');
|
||||||
var fs: typeof NodeJS.fs = require('fs');
|
var fs: typeof NodeJS.fs = require('fs');
|
||||||
|
|
||||||
var rl = readline.createInterface({
|
var rl = readline.createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
output: process.stdout,
|
output: process.stdout,
|
||||||
terminal: false,
|
terminal: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
class Logger implements ts.server.Logger {
|
class Logger implements ts.server.Logger {
|
||||||
fd = -1;
|
fd = -1;
|
||||||
seq = 0;
|
seq = 0;
|
||||||
|
@ -71,17 +71,17 @@ module ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IOSession extends Session {
|
class IOSession extends Session {
|
||||||
protocol: NodeJS._debugger.Protocol;
|
protocol: NodeJS._debugger.Protocol;
|
||||||
|
|
||||||
constructor(host: ServerHost, logger: ts.server.Logger, useProtocol: boolean, prettyJSON: boolean) {
|
constructor(host: ServerHost, logger: ts.server.Logger, useProtocol: boolean, prettyJSON: boolean) {
|
||||||
super(host, logger, useProtocol, prettyJSON);
|
super(host, logger, useProtocol, prettyJSON);
|
||||||
if (useProtocol) {
|
if (useProtocol) {
|
||||||
this.initProtocol();
|
this.initProtocol();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initProtocol() {
|
initProtocol() {
|
||||||
this.protocol = new nodeproto.Protocol();
|
this.protocol = new nodeproto.Protocol();
|
||||||
// note: onResponse was named by nodejs authors; we are re-purposing the Protocol
|
// note: onResponse was named by nodejs authors; we are re-purposing the Protocol
|
||||||
|
@ -89,25 +89,16 @@ module ts.server {
|
||||||
this.protocol.onResponse = (pkt) => {
|
this.protocol.onResponse = (pkt) => {
|
||||||
this.handleRequest(pkt);
|
this.handleRequest(pkt);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRequest(req: NodeJS._debugger.Packet) {
|
handleRequest(req: NodeJS._debugger.Packet) {
|
||||||
this.projectService.log("Got JSON msg:\n" + req.raw);
|
this.projectService.log("Got JSON msg:\n" + req.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
listen() {
|
listen() {
|
||||||
rl.on('line',(input: string) => {
|
rl.on('line',(input: string) => {
|
||||||
var cmd = input.trim();
|
var message = input.trim();
|
||||||
if (cmd.indexOf("{") == 0) {
|
this.onMessage(message);
|
||||||
// assumption is JSON on single line
|
|
||||||
// plan is to also carry this protocol
|
|
||||||
// over tcp, in which case JSON would
|
|
||||||
// have a Content-Length header
|
|
||||||
this.executeJSONcmd(cmd);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.executeCmd(cmd);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
rl.on('close',() => {
|
rl.on('close',() => {
|
||||||
|
@ -115,20 +106,13 @@ module ts.server {
|
||||||
this.projectService.log("Exiting...");
|
this.projectService.log("Exiting...");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This places log file in the directory containing editorServices.js
|
// This places log file in the directory containing editorServices.js
|
||||||
// TODO: check that this location is writable
|
// TODO: check that this location is writable
|
||||||
var logger = new Logger(__dirname + "/.log" + process.pid.toString());
|
var logger = new Logger(__dirname + "/.log" + process.pid.toString());
|
||||||
|
|
||||||
var host: ServerHost = ts.sys;
|
// Start listening
|
||||||
|
new IOSession(ts.sys, logger, /* useProtocol */ true, /* prettyJSON */ false).listen();
|
||||||
// Wire the debugging interface
|
|
||||||
if (!host.getDebuggerClient) {
|
|
||||||
host.getDebuggerClient = () => new nodeproto.Client();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start listening
|
|
||||||
new IOSession(host, logger, /* useProtocol */ true, /* prettyJSON */ false).listen();
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue