Recover from git corruption
This commit is contained in:
parent
99373dbd89
commit
a0b557e1e2
|
@ -128,7 +128,9 @@ module Harness.LanguageService {
|
|||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
}
|
||||
|
||||
public getNewLine(): string {
return "\r\n";
}
|
||||
public getNewLine(): string {
|
||||
return "\r\n";
|
||||
}
|
||||
|
||||
public getFilenames(): string[] {
|
||||
var fileNames: string[] = [];
|
||||
|
@ -435,12 +437,21 @@ module Harness.LanguageService {
|
|||
}
|
||||
|
||||
// Server adapter
|
||||
class ServerLanguageServiceHost extends NativeLanguageServiceHost {
|
||||
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
|
||||
private client: ts.server.SessionClient;
|
||||
|
||||
constructor(cancellationToken: ts.CancellationToken, settings: ts.CompilerOptions) {
|
||||
super(cancellationToken, settings);
|
||||
}
|
||||
|
||||
onMessage(message: string): void {
|
||||
|
||||
}
|
||||
|
||||
writeMessage(message: string): void {
|
||||
|
||||
}
|
||||
|
||||
setClient(client: ts.server.SessionClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
@ -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 {
|
||||
private host: ServerLanguageServiceHost;
|
||||
private host: SessionClientHost;
|
||||
private client: ts.server.SessionClient;
|
||||
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.client = new ts.server.SessionClient(this.host, /*abbreviate*/ true);
|
||||
this.host.setClient(this.client);
|
||||
// This host is just a proxy for the clientHost, it uses the client
|
||||
// host to answer server queries about files on disk
|
||||
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; }
|
||||
getLanguageService(): ts.LanguageService { return this.client; }
|
||||
|
|
|
@ -3,172 +3,44 @@
|
|||
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 {
|
||||
this.lastReply = 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 {
|
||||
}
|
||||
writeMessage(message: string): 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> = {};
|
||||
private lineMaps: ts.Map<number[]> = {};
|
||||
private messages: 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()
|
||||
}
|
||||
constructor(private host: SessionClientHost) {
|
||||
}
|
||||
|
||||
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.");
|
||||
|
||||
var expantionTable: ts.Map<string> = {};
|
||||
for (var p in abbriviationTable) {
|
||||
if (abbriviationTable.hasOwnProperty(p)) {
|
||||
expantionTable[abbriviationTable[p]] = p;
|
||||
}
|
||||
}
|
||||
this.expantionTable = expantionTable;
|
||||
public onMessage(message: string): void {
|
||||
this.messages.push(message);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
private writeMessage(message: string): void {
|
||||
this.host.writeMessage(message);
|
||||
}
|
||||
|
||||
// Substitute the name if applicaple
|
||||
var substitution = ts.lookUp(this.expantionTable, p);
|
||||
if (substitution) {
|
||||
(<any>obj)[substitution] = (<any>obj)[p];
|
||||
(<any>obj)[p] = undefined;
|
||||
}
|
||||
}
|
||||
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 obj;
|
||||
return lineMap;
|
||||
}
|
||||
|
||||
private lineColToPosition(fileName: string, lineCol: ServerProtocol.LineCol): number {
|
||||
return this.host.lineColToPosition(fileName, lineCol.line, lineCol.col);
|
||||
return ts.computePositionFromLineAndCharacter(this.getLineMap(fileName), lineCol.line, lineCol.col);
|
||||
}
|
||||
|
||||
private positionToOneBasedLineCol(fileName: string, position: number): ServerProtocol.LineCol {
|
||||
var lineCol = this.host.positionToZeroBasedLineCol(fileName, position);
|
||||
var lineCol = ts.computeLineAndCharacterOfPosition(this.getLineMap(fileName), position);
|
||||
return {
|
||||
line: lineCol.line + 1,
|
||||
col: lineCol.character + 1
|
||||
line: lineCol.line,
|
||||
col: lineCol.character
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -206,7 +78,7 @@ module ts.server {
|
|||
arguments: arguments
|
||||
};
|
||||
|
||||
this.session.executeJSONcmd(JSON.stringify(request));
|
||||
this.writeMessage(JSON.stringify(request));
|
||||
|
||||
return <T>request;
|
||||
}
|
||||
|
@ -214,8 +86,7 @@ module ts.server {
|
|||
private processResponse<T extends ServerProtocol.Response>(request: ServerProtocol.Request): T {
|
||||
debugger;
|
||||
|
||||
var lastMessage = this.host.lastReply;
|
||||
this.host.lastReply = undefined;
|
||||
var lastMessage = this.messages.shift();
|
||||
Debug.assert(!!lastMessage, "Did not recieve any responses.");
|
||||
|
||||
// Read the content length
|
||||
|
@ -250,10 +121,6 @@ module ts.server {
|
|||
|
||||
Debug.assert(!!response.body, "Malformed response: Unexpected empty response body.");
|
||||
|
||||
if (this.expantionTable) {
|
||||
// Expand the response if abbreviated
|
||||
return this.expand(response);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -268,6 +135,9 @@ module ts.server {
|
|||
}
|
||||
|
||||
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 args: ServerProtocol.ChangeRequestArgs = {
|
||||
file: fileName,
|
||||
|
@ -326,7 +196,7 @@ module ts.server {
|
|||
getNavigateToItems(searchTerm: string): NavigateToItem[] {
|
||||
var args: ServerProtocol.NavtoRequestArgs = {
|
||||
searchTerm,
|
||||
file: this.host.getFileNames()[0]
|
||||
file: this.host.getScriptFileNames()[0]
|
||||
};
|
||||
|
||||
var request = this.processRequest<ServerProtocol.NavtoRequest>(CommandNames.Navto, args);
|
||||
|
@ -369,7 +239,7 @@ module ts.server {
|
|||
}
|
||||
|
||||
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[] {
|
||||
|
|
|
@ -425,7 +425,8 @@ module ts.server {
|
|||
if (projectOptions.compilerOptions) {
|
||||
this.compilerService.setCompilerOptions(projectOptions.compilerOptions);
|
||||
}
|
||||
// TODO: format code options
}
|
||||
// TODO: format code options
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
server that the client has file open. The server will not
|
||||
|
@ -483,8 +471,8 @@ declare module ServerProtocol {
|
|||
kindModifiers?: string;
|
||||
/**
|
||||
The file in which the symbol is found; the value of this
|
||||
field will always be a string unless the client opts-in to
|
||||
file encoding by sending the "abbrev" request.
|
||||
field will always be a string, number of a mapping between
|
||||
a string and a number.
|
||||
*/
|
||||
file: EncodedFile;
|
||||
/** The location within file at which the symbol is found*/
|
||||
|
@ -528,27 +516,6 @@ declare module ServerProtocol {
|
|||
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
|
||||
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;
|
||||
|
||||
/**
|
||||
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. */
|
||||
export interface BraceResponse extends Response {
|
||||
body?: TextSpan[];
|
||||
|
|
|
@ -97,17 +97,8 @@ module ts.server {
|
|||
|
||||
listen() {
|
||||
rl.on('line',(input: string) => {
|
||||
var cmd = input.trim();
|
||||
if (cmd.indexOf("{") == 0) {
|
||||
// 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);
|
||||
}
|
||||
var message = input.trim();
|
||||
this.onMessage(message);
|
||||
});
|
||||
|
||||
rl.on('close',() => {
|
||||
|
@ -122,13 +113,6 @@ module ts.server {
|
|||
// TODO: check that this location is writable
|
||||
var logger = new Logger(__dirname + "/.log" + process.pid.toString());
|
||||
|
||||
var host: ServerHost = ts.sys;
|
||||
|
||||
// Wire the debugging interface
|
||||
if (!host.getDebuggerClient) {
|
||||
host.getDebuggerClient = () => new nodeproto.Client();
|
||||
}
|
||||
|
||||
// Start listening
|
||||
new IOSession(host, logger, /* useProtocol */ true, /* prettyJSON */ false).listen();
|
||||
new IOSession(ts.sys, logger, /* useProtocol */ true, /* prettyJSON */ false).listen();
|
||||
}
|
Loading…
Reference in a new issue