Merge branch 'master' into limitNavigateTo
This commit is contained in:
commit
8d7791c579
33
Jakefile
33
Jakefile
|
@ -8,6 +8,7 @@ var child_process = require("child_process");
|
|||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
var servicesDirectory = "src/services/";
|
||||
var serverDirectory = "src/server/";
|
||||
var harnessDirectory = "src/harness/";
|
||||
var libraryDirectory = "src/lib/";
|
||||
var scriptsDirectory = "scripts/";
|
||||
|
@ -90,6 +91,16 @@ var servicesSources = [
|
|||
return path.join(servicesDirectory, f);
|
||||
}));
|
||||
|
||||
var serverSources = [
|
||||
"node.d.ts",
|
||||
"editorServices.ts",
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"server.ts"
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
});
|
||||
|
||||
var definitionsRoots = [
|
||||
"compiler/types.d.ts",
|
||||
"compiler/scanner.d.ts",
|
||||
|
@ -130,6 +141,13 @@ var harnessSources = [
|
|||
"services/preProcessFile.ts"
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
"protocol.d.ts",
|
||||
"session.ts",
|
||||
"client.ts",
|
||||
"editorServices.ts",
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
}));
|
||||
|
||||
var librarySourceMap = [
|
||||
|
@ -327,6 +345,7 @@ var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
|||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
|
@ -336,7 +355,10 @@ compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].conca
|
|||
/*preserveConstEnums*/ true,
|
||||
/*keepComments*/ false,
|
||||
/*noResolve*/ false,
|
||||
/*stripInternal*/ false);
|
||||
/*stripInternal*/ false,
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
});
|
||||
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
|
@ -378,9 +400,12 @@ compileFile(nodeDefinitionsFile, servicesSources,[builtLocalDirectory, copyright
|
|||
jake.rmRf(tempDirPath, {silent: true});
|
||||
});
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile]);
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
|
@ -435,7 +460,7 @@ task("generate-spec", [specMd])
|
|||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
|
||||
var expectedFiles = [tscFile, servicesFile, nodeDefinitionsFile, standaloneDefinitionsFile, internalNodeDefinitionsFile, internalStandaloneDefinitionsFile].concat(libraryTargets);
|
||||
var expectedFiles = [tscFile, servicesFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, internalNodeDefinitionsFile, internalStandaloneDefinitionsFile].concat(libraryTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
|
@ -542,7 +567,7 @@ task("runtests", ["tests", builtLocalDirectory], function() {
|
|||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
testTimeout = 50000;
|
||||
testTimeout = 100000;
|
||||
}
|
||||
|
||||
colors = process.env.colors || process.env.color
|
||||
|
|
2
bin/tsserver
Normal file
2
bin/tsserver
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env node
|
||||
require('./tsserver.js')
|
|
@ -25,9 +25,10 @@
|
|||
"url": "https://github.com/Microsoft/TypeScript.git"
|
||||
},
|
||||
"preferGlobal": true,
|
||||
"main": "./bin/typescriptServices.js",
|
||||
"main": "./bin/typescript.js",
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc"
|
||||
"tsc": "./bin/tsc",
|
||||
"tsserver": "./bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
|
|
|
@ -282,6 +282,8 @@ module FourSlash {
|
|||
return new Harness.LanguageService.NativeLanugageServiceAdapter(cancellationToken, compilationOptions);
|
||||
case FourSlashTestType.Shims:
|
||||
return new Harness.LanguageService.ShimLanugageServiceAdapter(cancellationToken, compilationOptions);
|
||||
case FourSlashTestType.Server:
|
||||
return new Harness.LanguageService.ServerLanugageServiceAdapter(cancellationToken, compilationOptions);
|
||||
default:
|
||||
throw new Error("Unknown FourSlash test type: ");
|
||||
}
|
||||
|
@ -418,6 +420,9 @@ module FourSlash {
|
|||
this.activeFile = fileToOpen;
|
||||
var fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), '').substr(1);
|
||||
this.scenarioActions.push('<OpenFile FileName="" SrcFileId="' + fileName + '" FileId="' + fileName + '" />');
|
||||
|
||||
// Let the host know that this file is now open
|
||||
this.languageServiceAdapterHost.openFile(fileToOpen.fileName);
|
||||
}
|
||||
|
||||
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
|
||||
|
@ -1927,7 +1932,7 @@ module FourSlash {
|
|||
}
|
||||
|
||||
var missingItem = { name: name, kind: kind };
|
||||
this.raiseError('verifyGetScriptLexicalStructureListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items) + ')');
|
||||
this.raiseError('verifyGetScriptLexicalStructureListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items, null, " ") + ')');
|
||||
}
|
||||
|
||||
private navigationBarItemsContains(items: ts.NavigationBarItem[], name: string, kind: string) {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
const enum FourSlashTestType {
|
||||
Native,
|
||||
Shims
|
||||
Shims,
|
||||
Server
|
||||
}
|
||||
|
||||
class FourSlashRunner extends RunnerBase {
|
||||
|
@ -22,6 +23,10 @@ class FourSlashRunner extends RunnerBase {
|
|||
this.basePath = 'tests/cases/fourslash/shims';
|
||||
this.testSuiteName = 'fourslash-shims';
|
||||
break;
|
||||
case FourSlashTestType.Server:
|
||||
this.basePath = 'tests/cases/fourslash/server';
|
||||
this.testSuiteName = 'fourslash-server';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
|
||||
/// <reference path='..\services\services.ts' />
|
||||
/// <reference path='..\services\shims.ts' />
|
||||
/// <reference path='..\server\session.ts' />
|
||||
/// <reference path='..\server\client.ts' />
|
||||
/// <reference path='..\server\node.d.ts' />
|
||||
/// <reference path='external\mocha.d.ts'/>
|
||||
/// <reference path='external\chai.d.ts'/>
|
||||
/// <reference path='sourceMapRecorder.ts'/>
|
||||
/// <reference path='runnerbase.ts'/>
|
||||
|
||||
declare var require: any;
|
||||
declare var process: any;
|
||||
var Buffer = require('buffer').Buffer;
|
||||
var Buffer: BufferConstructor = require('buffer').Buffer;
|
||||
|
||||
// this will work in the browser via browserify
|
||||
var _chai: typeof chai = require('chai');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/// <reference path='..\services\services.ts' />
|
||||
/// <reference path='..\services\shims.ts' />
|
||||
/// <reference path='..\server\client.ts' />
|
||||
/// <reference path='harness.ts' />
|
||||
|
||||
module Harness.LanguageService {
|
||||
|
@ -23,18 +24,18 @@ module Harness.LanguageService {
|
|||
this.version++;
|
||||
}
|
||||
|
||||
public editContent(minChar: number, limChar: number, newText: string): void {
|
||||
public editContent(start: number, end: number, newText: string): void {
|
||||
// Apply edits
|
||||
var prefix = this.content.substring(0, minChar);
|
||||
var prefix = this.content.substring(0, start);
|
||||
var middle = newText;
|
||||
var suffix = this.content.substring(limChar);
|
||||
var suffix = this.content.substring(end);
|
||||
this.setContent(prefix + middle + suffix);
|
||||
|
||||
// Store edit range + new length of script
|
||||
this.editRanges.push({
|
||||
length: this.content.length,
|
||||
textChangeRange: ts.createTextChangeRange(
|
||||
ts.createTextSpanFromBounds(minChar, limChar), newText.length)
|
||||
ts.createTextSpanFromBounds(start, end), newText.length)
|
||||
});
|
||||
|
||||
// Update version #
|
||||
|
@ -145,26 +146,19 @@ module Harness.LanguageService {
|
|||
this.fileNameToScript[fileName] = new ScriptInfo(fileName, content);
|
||||
}
|
||||
|
||||
public updateScript(fileName: string, content: string) {
|
||||
public editScript(fileName: string, start: number, end: number, newText: string) {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
if (script !== null) {
|
||||
script.updateContent(content);
|
||||
return;
|
||||
}
|
||||
|
||||
this.addScript(fileName, content);
|
||||
}
|
||||
|
||||
public editScript(fileName: string, minChar: number, limChar: number, newText: string) {
|
||||
var script = this.getScriptInfo(fileName);
|
||||
if (script !== null) {
|
||||
script.editContent(minChar, limChar, newText);
|
||||
script.editContent(start, end, newText);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("No script with name '" + fileName + "'");
|
||||
}
|
||||
|
||||
public openFile(fileName: string): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 1 based index
|
||||
* @param col 1 based index
|
||||
|
@ -236,8 +230,7 @@ module Harness.LanguageService {
|
|||
getFilenames(): string[] { return this.nativeHost.getFilenames(); }
|
||||
getScriptInfo(fileName: string): ScriptInfo { return this.nativeHost.getScriptInfo(fileName); }
|
||||
addScript(fileName: string, content: string): void { this.nativeHost.addScript(fileName, content); }
|
||||
updateScript(fileName: string, content: string): void { return this.nativeHost.updateScript(fileName, content); }
|
||||
editScript(fileName: string, minChar: number, limChar: number, newText: string): void { this.nativeHost.editScript(fileName, minChar, limChar, newText); }
|
||||
editScript(fileName: string, start: number, end: number, newText: string): void { this.nativeHost.editScript(fileName, start, end, newText); }
|
||||
lineColToPosition(fileName: string, line: number, col: number): number { return this.nativeHost.lineColToPosition(fileName, line, col); }
|
||||
positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter { return this.nativeHost.positionToZeroBasedLineCol(fileName, position); }
|
||||
|
||||
|
@ -442,5 +435,156 @@ module Harness.LanguageService {
|
|||
return convertResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Server adapter
|
||||
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;
|
||||
}
|
||||
|
||||
openFile(fileName: string): void {
|
||||
super.openFile(fileName);
|
||||
this.client.openFile(fileName);
|
||||
}
|
||||
|
||||
editScript(fileName: string, start: number, end: number, newText: string) {
|
||||
super.editScript(fileName, start, end, newText);
|
||||
this.client.changeFile(fileName, start, end, newText);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
|
||||
fileName = Harness.Compiler.defaultLibFileName;
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
watchFile(fileName: string, callback: (fileName: string) => void): ts.FileWatcher {
|
||||
return { close() { } };
|
||||
}
|
||||
|
||||
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: SessionClientHost;
|
||||
private client: ts.server.SessionClient;
|
||||
constructor(cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions) {
|
||||
// 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 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);
|
||||
|
||||
// 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; }
|
||||
getClassifier(): ts.Classifier { throw new Error("getClassifier is not available using the server interface."); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { throw new Error("getPreProcessedFileInfo is not available using the server interface."); }
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,9 @@ if (testConfigFile !== '') {
|
|||
case 'fourslash-shims':
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
|
||||
break;
|
||||
case 'fourslash-server':
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Server));
|
||||
break;
|
||||
case 'fourslash-generated':
|
||||
runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native));
|
||||
break;
|
||||
|
@ -95,6 +98,7 @@ if (runners.length === 0) {
|
|||
// language services
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Native));
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
|
||||
runners.push(new FourSlashRunner(FourSlashTestType.Server));
|
||||
//runners.push(new GeneratedFourslashRunner());
|
||||
}
|
||||
|
||||
|
|
494
src/server/client.ts
Normal file
494
src/server/client.ts
Normal file
|
@ -0,0 +1,494 @@
|
|||
/// <reference path="session.ts" />
|
||||
|
||||
module ts.server {
|
||||
|
||||
export interface SessionClientHost extends LanguageServiceHost {
|
||||
writeMessage(message: string): void;
|
||||
}
|
||||
|
||||
interface CompletionEntry extends CompletionInfo {
|
||||
fileName: string;
|
||||
position: number;
|
||||
}
|
||||
|
||||
interface RenameEntry extends RenameInfo {
|
||||
fileName: string;
|
||||
position: number;
|
||||
locations: RenameLocation[];
|
||||
findInStrings: boolean;
|
||||
findInComments: boolean;
|
||||
}
|
||||
|
||||
export class SessionClient implements LanguageService {
|
||||
private sequence: number = 0;
|
||||
private fileMapping: ts.Map<string> = {};
|
||||
private lineMaps: ts.Map<number[]> = {};
|
||||
private messages: string[] = [];
|
||||
private lastRenameEntry: RenameEntry;
|
||||
|
||||
constructor(private host: SessionClientHost) {
|
||||
}
|
||||
|
||||
public onMessage(message: string): void {
|
||||
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: protocol.Location): number {
|
||||
return ts.computePositionFromLineAndCharacter(this.getLineMap(fileName), lineCol.line, lineCol.col);
|
||||
}
|
||||
|
||||
private positionToOneBasedLineCol(fileName: string, position: number): protocol.Location {
|
||||
var lineCol = ts.computeLineAndCharacterOfPosition(this.getLineMap(fileName), position);
|
||||
return {
|
||||
line: lineCol.line,
|
||||
col: lineCol.character
|
||||
};
|
||||
}
|
||||
|
||||
private convertCodeEditsToTextChange(fileName: string, codeEdit: protocol.CodeEdit): ts.TextChange {
|
||||
var start = this.lineColToPosition(fileName, codeEdit.start);
|
||||
var end = this.lineColToPosition(fileName, codeEdit.end);
|
||||
|
||||
return {
|
||||
span: ts.createTextSpanFromBounds(start, end),
|
||||
newText: codeEdit.newText
|
||||
};
|
||||
}
|
||||
|
||||
private processRequest<T extends protocol.Request>(command: string, arguments?: any): T {
|
||||
var request: protocol.Request = {
|
||||
seq: this.sequence++,
|
||||
type: "request",
|
||||
command: command,
|
||||
arguments: arguments
|
||||
};
|
||||
|
||||
this.writeMessage(JSON.stringify(request));
|
||||
|
||||
return <T>request;
|
||||
}
|
||||
|
||||
private processResponse<T extends protocol.Response>(request: protocol.Request): T {
|
||||
var lastMessage = this.messages.shift();
|
||||
Debug.assert(!!lastMessage, "Did not recieve any responses.");
|
||||
|
||||
// Read the content length
|
||||
var contentLengthPrefix = "Content-Length: ";
|
||||
var lines = lastMessage.split("\r\n");
|
||||
Debug.assert(lines.length >= 2, "Malformed response: Expected 3 lines in the response.");
|
||||
|
||||
var contentLengthText = lines[0];
|
||||
Debug.assert(contentLengthText.indexOf(contentLengthPrefix) === 0, "Malformed response: Response text did not contain content-length header.");
|
||||
var contentLength = parseInt(contentLengthText.substring(contentLengthPrefix.length));
|
||||
|
||||
// Read the body
|
||||
var responseBody = lines[2];
|
||||
|
||||
// Verify content length
|
||||
Debug.assert(responseBody.length + 1 === contentLength, "Malformed response: Content length did not match the response's body length.");
|
||||
|
||||
try {
|
||||
var response: T = JSON.parse(responseBody);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("Malformed response: Failed to parse server response: " + lastMessage + ". \r\n Error detailes: " + e.message);
|
||||
}
|
||||
|
||||
// verify the sequence numbers
|
||||
Debug.assert(response.request_seq === request.seq, "Malformed response: response sequance number did not match request sequence number.");
|
||||
|
||||
// unmarshal errors
|
||||
if (!response.success) {
|
||||
throw new Error("Error " + response.message);
|
||||
}
|
||||
|
||||
Debug.assert(!!response.body, "Malformed response: Unexpected empty response body.");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
openFile(fileName: string): void {
|
||||
var args: protocol.FileRequestArgs = { file: fileName };
|
||||
this.processRequest(CommandNames.Open, args);
|
||||
}
|
||||
|
||||
closeFile(fileName: string): void {
|
||||
var args: protocol.FileRequestArgs = { file: fileName };
|
||||
this.processRequest(CommandNames.Close, args);
|
||||
}
|
||||
|
||||
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 endLineCol = this.positionToOneBasedLineCol(fileName, end);
|
||||
|
||||
var args: protocol.ChangeRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
endLine: endLineCol.line,
|
||||
endCol: endLineCol.col,
|
||||
insertString: newText
|
||||
};
|
||||
|
||||
this.processRequest(CommandNames.Change, args);
|
||||
}
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.FileLocationRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.QuickInfoRequest>(CommandNames.Quickinfo, args);
|
||||
var response = this.processResponse<protocol.QuickInfoResponse>(request);
|
||||
|
||||
var start = this.lineColToPosition(fileName, response.body.start);
|
||||
var end = this.lineColToPosition(fileName, response.body.end);
|
||||
|
||||
return {
|
||||
kind: response.body.kind,
|
||||
kindModifiers: response.body.kindModifiers,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end),
|
||||
displayParts: [{ kind: "text", text: response.body.displayString }],
|
||||
documentation: [{ kind: "text", text: response.body.documentation }]
|
||||
};
|
||||
}
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.CompletionsRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
prefix: undefined
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.CompletionsRequest>(CommandNames.Completions, args);
|
||||
var response = this.processResponse<protocol.CompletionsResponse>(request);
|
||||
|
||||
return {
|
||||
isMemberCompletion: false,
|
||||
isNewIdentifierLocation: false,
|
||||
entries: response.body,
|
||||
fileName: fileName,
|
||||
position: position
|
||||
};
|
||||
}
|
||||
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.CompletionDetailsRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
entryNames: [entryName]
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.CompletionDetailsRequest>(CommandNames.CompletionDetails, args);
|
||||
var response = this.processResponse<protocol.CompletionDetailsResponse>(request);
|
||||
Debug.assert(response.body.length == 1, "Unexpected length of completion details response body.");
|
||||
return response.body[0];
|
||||
}
|
||||
|
||||
getNavigateToItems(searchTerm: string): NavigateToItem[] {
|
||||
var args: protocol.NavtoRequestArgs = {
|
||||
searchTerm,
|
||||
file: this.host.getScriptFileNames()[0]
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.NavtoRequest>(CommandNames.Navto, args);
|
||||
var response = this.processResponse<protocol.NavtoResponse>(request);
|
||||
|
||||
return response.body.map(entry => {
|
||||
var fileName = entry.file;
|
||||
var start = this.lineColToPosition(fileName, entry.start);
|
||||
var end = this.lineColToPosition(fileName, entry.end);
|
||||
|
||||
return {
|
||||
name: entry.name,
|
||||
containerName: entry.containerName || "",
|
||||
containerKind: entry.containerKind || "",
|
||||
kind: entry.kind,
|
||||
kindModifiers: entry.kindModifiers,
|
||||
matchKind: entry.matchKind,
|
||||
fileName: fileName,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): ts.TextChange[] {
|
||||
var startLineCol = this.positionToOneBasedLineCol(fileName, start);
|
||||
var endLineCol = this.positionToOneBasedLineCol(fileName, end);
|
||||
var args: protocol.FormatRequestArgs = {
|
||||
file: fileName,
|
||||
line: startLineCol.line,
|
||||
col: startLineCol.col,
|
||||
endLine: endLineCol.line,
|
||||
endCol: endLineCol.col,
|
||||
};
|
||||
|
||||
// TODO: handle FormatCodeOptions
|
||||
var request = this.processRequest<protocol.FormatRequest>(CommandNames.Format, args);
|
||||
var response = this.processResponse<protocol.FormatResponse>(request);
|
||||
|
||||
return response.body.map(entry=> this.convertCodeEditsToTextChange(fileName, entry));
|
||||
}
|
||||
|
||||
getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): ts.TextChange[] {
|
||||
return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName).getLength(), options);
|
||||
}
|
||||
|
||||
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): ts.TextChange[] {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.FormatOnKeyRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
key: key
|
||||
};
|
||||
|
||||
// TODO: handle FormatCodeOptions
|
||||
var request = this.processRequest<protocol.FormatOnKeyRequest>(CommandNames.Formatonkey, args);
|
||||
var response = this.processResponse<protocol.FormatResponse>(request);
|
||||
|
||||
return response.body.map(entry=> this.convertCodeEditsToTextChange(fileName, entry));
|
||||
}
|
||||
|
||||
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.FileLocationRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.DefinitionRequest>(CommandNames.Definition, args);
|
||||
var response = this.processResponse<protocol.DefinitionResponse>(request);
|
||||
|
||||
return response.body.map(entry => {
|
||||
var fileName = entry.file;
|
||||
var start = this.lineColToPosition(fileName, entry.start);
|
||||
var end = this.lineColToPosition(fileName, entry.end);
|
||||
return {
|
||||
containerKind: "",
|
||||
containerName: "",
|
||||
fileName: fileName,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end),
|
||||
kind: "",
|
||||
name: ""
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.FileLocationRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.ReferencesRequest>(CommandNames.References, args);
|
||||
var response = this.processResponse<protocol.ReferencesResponse>(request);
|
||||
|
||||
return response.body.refs.map(entry => {
|
||||
var fileName = entry.file;
|
||||
var start = this.lineColToPosition(fileName, entry.start);
|
||||
var end = this.lineColToPosition(fileName, entry.end);
|
||||
return {
|
||||
fileName: fileName,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end),
|
||||
isWriteAccess: entry.isWriteAccess,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getEmitOutput(fileName: string): EmitOutput {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getSyntacticDiagnostics(fileName: string): Diagnostic[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getSemanticDiagnostics(fileName: string): Diagnostic[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getCompilerOptionsDiagnostics(): Diagnostic[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getRenameInfo(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameInfo {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.RenameRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
findInStrings,
|
||||
findInComments
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.RenameRequest>(CommandNames.Rename, args);
|
||||
var response = this.processResponse<protocol.RenameResponse>(request);
|
||||
var locations: RenameLocation[] = [];
|
||||
response.body.locs.map((entry: protocol.SpanGroup) => {
|
||||
var fileName = entry.file;
|
||||
entry.locs.map((loc: protocol.TextSpan) => {
|
||||
var start = this.lineColToPosition(fileName, loc.start);
|
||||
var end = this.lineColToPosition(fileName, loc.end);
|
||||
locations.push({
|
||||
textSpan: ts.createTextSpanFromBounds(start, end),
|
||||
fileName: fileName
|
||||
});
|
||||
});
|
||||
});
|
||||
return this.lastRenameEntry = {
|
||||
canRename: response.body.info.canRename,
|
||||
displayName: response.body.info.displayName,
|
||||
fullDisplayName: response.body.info.fullDisplayName,
|
||||
kind: response.body.info.kind,
|
||||
kindModifiers: response.body.info.kindModifiers,
|
||||
localizedErrorMessage: response.body.info.localizedErrorMessage,
|
||||
triggerSpan: ts.createTextSpanFromBounds(position, position),
|
||||
fileName: fileName,
|
||||
position: position,
|
||||
findInStrings: findInStrings,
|
||||
findInComments: findInComments,
|
||||
locations: locations
|
||||
};
|
||||
}
|
||||
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
|
||||
if (!this.lastRenameEntry ||
|
||||
this.lastRenameEntry.fileName !== fileName ||
|
||||
this.lastRenameEntry.position !== position ||
|
||||
this.lastRenameEntry.findInStrings != findInStrings ||
|
||||
this.lastRenameEntry.findInComments != findInComments) {
|
||||
this.getRenameInfo(fileName, position, findInStrings, findInComments);
|
||||
}
|
||||
|
||||
return this.lastRenameEntry.locations;
|
||||
}
|
||||
|
||||
decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string): NavigationBarItem[] {
|
||||
if (!items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return items.map(item => ({
|
||||
text: item.text,
|
||||
kind: item.kind,
|
||||
kindModifiers: item.kindModifiers || "",
|
||||
spans: item.spans.map(span=> createTextSpanFromBounds(this.lineColToPosition(fileName, span.start), this.lineColToPosition(fileName, span.end))),
|
||||
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
|
||||
indent: 0,
|
||||
bolded: false,
|
||||
grayed: false
|
||||
}));
|
||||
}
|
||||
|
||||
getNavigationBarItems(fileName: string): NavigationBarItem[] {
|
||||
var args: protocol.FileRequestArgs = {
|
||||
file: fileName
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.NavBarRequest>(CommandNames.NavBar, args);
|
||||
var response = this.processResponse<protocol.NavBarResponse>(request);
|
||||
|
||||
return this.decodeNavigationBarItems(response.body, fileName);
|
||||
}
|
||||
|
||||
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getOutliningSpans(fileName: string): OutliningSpan[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] {
|
||||
var lineCol = this.positionToOneBasedLineCol(fileName, position);
|
||||
var args: protocol.FileLocationRequestArgs = {
|
||||
file: fileName,
|
||||
line: lineCol.line,
|
||||
col: lineCol.col,
|
||||
};
|
||||
|
||||
var request = this.processRequest<protocol.BraceRequest>(CommandNames.Brace, args);
|
||||
var response = this.processResponse<protocol.BraceResponse>(request);
|
||||
|
||||
return response.body.map(entry => {
|
||||
var start = this.lineColToPosition(fileName, entry.start);
|
||||
var end = this.lineColToPosition(fileName, entry.end);
|
||||
return {
|
||||
start: start,
|
||||
length: end - start,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getProgram(): Program {
|
||||
throw new Error("SourceFile objects are not serializable through the server protocol.");
|
||||
}
|
||||
|
||||
getSourceFile(fileName: string): SourceFile {
|
||||
throw new Error("SourceFile objects are not serializable through the server protocol.");
|
||||
}
|
||||
|
||||
cleanupSemanticCache(): void {
|
||||
throw new Error("cleanupSemanticCache is not available through the server layer.");
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
throw new Error("dispose is not available through the server layer.");
|
||||
}
|
||||
}
|
||||
}
|
1646
src/server/editorServices.ts
Normal file
1646
src/server/editorServices.ts
Normal file
File diff suppressed because it is too large
Load diff
677
src/server/node.d.ts
vendored
Normal file
677
src/server/node.d.ts
vendored
Normal file
|
@ -0,0 +1,677 @@
|
|||
// Type definitions for Node.js v0.10.1
|
||||
// Project: http://nodejs.org/
|
||||
// Definitions by: Microsoft TypeScript <http://typescriptlang.org>, DefinitelyTyped <https://github.com/borisyankov/DefinitelyTyped>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/************************************************
|
||||
* *
|
||||
* Node.js v0.10.1 API *
|
||||
* *
|
||||
************************************************/
|
||||
|
||||
/************************************************
|
||||
* *
|
||||
* GLOBAL *
|
||||
* *
|
||||
************************************************/
|
||||
declare var process: NodeJS.Process;
|
||||
declare var global: any;
|
||||
|
||||
declare var __filename: string;
|
||||
declare var __dirname: string;
|
||||
|
||||
declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;
|
||||
declare function clearTimeout(timeoutId: NodeJS.Timer): void;
|
||||
declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;
|
||||
declare function clearInterval(intervalId: NodeJS.Timer): void;
|
||||
declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any;
|
||||
declare function clearImmediate(immediateId: any): void;
|
||||
|
||||
declare var require: {
|
||||
(id: string): any;
|
||||
resolve(id: string): string;
|
||||
cache: any;
|
||||
extensions: any;
|
||||
main: any;
|
||||
};
|
||||
|
||||
declare var module: {
|
||||
exports: any;
|
||||
require(id: string): any;
|
||||
id: string;
|
||||
filename: string;
|
||||
loaded: boolean;
|
||||
parent: any;
|
||||
children: any[];
|
||||
};
|
||||
|
||||
// Same as module.exports
|
||||
declare var exports: any;
|
||||
declare var SlowBuffer: {
|
||||
new (str: string, encoding?: string): Buffer;
|
||||
new (size: number): Buffer;
|
||||
new (size: Uint8Array): Buffer;
|
||||
new (array: any[]): Buffer;
|
||||
prototype: Buffer;
|
||||
isBuffer(obj: any): boolean;
|
||||
byteLength(string: string, encoding?: string): number;
|
||||
concat(list: Buffer[], totalLength?: number): Buffer;
|
||||
};
|
||||
|
||||
|
||||
// Buffer class
|
||||
interface Buffer extends NodeBuffer { }
|
||||
interface BufferConstructor {
|
||||
new (str: string, encoding ?: string): Buffer;
|
||||
new (size: number): Buffer;
|
||||
new (size: Uint8Array): Buffer;
|
||||
new (array: any[]): Buffer;
|
||||
prototype: Buffer;
|
||||
isBuffer(obj: any): boolean;
|
||||
byteLength(string: string, encoding ?: string): number;
|
||||
concat(list: Buffer[], totalLength ?: number): Buffer;
|
||||
}
|
||||
declare var Buffer: BufferConstructor;
|
||||
|
||||
/************************************************
|
||||
* *
|
||||
* GLOBAL INTERFACES *
|
||||
* *
|
||||
************************************************/
|
||||
declare module NodeJS {
|
||||
export interface ErrnoException extends Error {
|
||||
errno?: any;
|
||||
code?: string;
|
||||
path?: string;
|
||||
syscall?: string;
|
||||
}
|
||||
|
||||
export interface EventEmitter {
|
||||
addListener(event: string, listener: Function): EventEmitter;
|
||||
on(event: string, listener: Function): EventEmitter;
|
||||
once(event: string, listener: Function): EventEmitter;
|
||||
removeListener(event: string, listener: Function): EventEmitter;
|
||||
removeAllListeners(event?: string): EventEmitter;
|
||||
setMaxListeners(n: number): void;
|
||||
listeners(event: string): Function[];
|
||||
emit(event: string, ...args: any[]): boolean;
|
||||
}
|
||||
|
||||
export interface ReadableStream extends EventEmitter {
|
||||
readable: boolean;
|
||||
read(size?: number): any;
|
||||
setEncoding(encoding: string): void;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
pipe<T extends WritableStream>(destination: T, options?: { end?: boolean; }): T;
|
||||
unpipe<T extends WritableStream>(destination?: T): void;
|
||||
unshift(chunk: string): void;
|
||||
unshift(chunk: Buffer): void;
|
||||
wrap(oldStream: ReadableStream): ReadableStream;
|
||||
}
|
||||
|
||||
export interface WritableStream extends EventEmitter {
|
||||
writable: boolean;
|
||||
write(buffer: Buffer, cb?: Function): boolean;
|
||||
write(str: string, cb?: Function): boolean;
|
||||
write(str: string, encoding?: string, cb?: Function): boolean;
|
||||
end(): void;
|
||||
end(buffer: Buffer, cb?: Function): void;
|
||||
end(str: string, cb?: Function): void;
|
||||
end(str: string, encoding?: string, cb?: Function): void;
|
||||
}
|
||||
|
||||
export interface ReadWriteStream extends ReadableStream, WritableStream { }
|
||||
|
||||
export interface Process extends EventEmitter {
|
||||
stdout: WritableStream;
|
||||
stderr: WritableStream;
|
||||
stdin: ReadableStream;
|
||||
argv: string[];
|
||||
execPath: string;
|
||||
abort(): void;
|
||||
chdir(directory: string): void;
|
||||
cwd(): string;
|
||||
env: any;
|
||||
exit(code?: number): void;
|
||||
getgid(): number;
|
||||
setgid(id: number): void;
|
||||
setgid(id: string): void;
|
||||
getuid(): number;
|
||||
setuid(id: number): void;
|
||||
setuid(id: string): void;
|
||||
version: string;
|
||||
versions: {
|
||||
http_parser: string;
|
||||
node: string;
|
||||
v8: string;
|
||||
ares: string;
|
||||
uv: string;
|
||||
zlib: string;
|
||||
openssl: string;
|
||||
};
|
||||
config: {
|
||||
target_defaults: {
|
||||
cflags: any[];
|
||||
default_configuration: string;
|
||||
defines: string[];
|
||||
include_dirs: string[];
|
||||
libraries: string[];
|
||||
};
|
||||
variables: {
|
||||
clang: number;
|
||||
host_arch: string;
|
||||
node_install_npm: boolean;
|
||||
node_install_waf: boolean;
|
||||
node_prefix: string;
|
||||
node_shared_openssl: boolean;
|
||||
node_shared_v8: boolean;
|
||||
node_shared_zlib: boolean;
|
||||
node_use_dtrace: boolean;
|
||||
node_use_etw: boolean;
|
||||
node_use_openssl: boolean;
|
||||
target_arch: string;
|
||||
v8_no_strict_aliasing: number;
|
||||
v8_use_snapshot: boolean;
|
||||
visibility: string;
|
||||
};
|
||||
};
|
||||
kill(pid: number, signal?: string): void;
|
||||
pid: number;
|
||||
title: string;
|
||||
arch: string;
|
||||
platform: string;
|
||||
memoryUsage(): { rss: number; heapTotal: number; heapUsed: number; };
|
||||
nextTick(callback: Function): void;
|
||||
umask(mask?: number): number;
|
||||
uptime(): number;
|
||||
hrtime(time?: number[]): number[];
|
||||
|
||||
// Worker
|
||||
send? (message: any, sendHandle?: any): void;
|
||||
}
|
||||
|
||||
export interface Timer {
|
||||
ref(): void;
|
||||
unref(): void;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface NodeBuffer {
|
||||
[index: number]: number;
|
||||
write(string: string, offset?: number, length?: number, encoding?: string): number;
|
||||
toString(encoding?: string, start?: number, end?: number): string;
|
||||
toJSON(): any;
|
||||
length: number;
|
||||
copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
slice(start?: number, end?: number): Buffer;
|
||||
readUInt8(offset: number, noAsset?: boolean): number;
|
||||
readUInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readInt8(offset: number, noAssert?: boolean): number;
|
||||
readInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readFloatLE(offset: number, noAssert?: boolean): number;
|
||||
readFloatBE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleLE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleBE(offset: number, noAssert?: boolean): number;
|
||||
writeUInt8(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeUInt16LE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeUInt16BE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeUInt32LE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeUInt32BE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeInt8(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeInt16LE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeInt16BE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeInt32LE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeInt32BE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeFloatLE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeFloatBE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeDoubleLE(value: number, offset: number, noAssert?: boolean): void;
|
||||
writeDoubleBE(value: number, offset: number, noAssert?: boolean): void;
|
||||
fill(value: any, offset?: number, end?: number): void;
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
export interface Path {
|
||||
normalize(p: string): string;
|
||||
join(...paths: any[]): string;
|
||||
resolve(...pathSegments: any[]): string;
|
||||
relative(from: string, to: string): string;
|
||||
dirname(p: string): string;
|
||||
basename(p: string, ext?: string): string;
|
||||
extname(p: string): string;
|
||||
sep: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
export interface ReadLineInstance extends EventEmitter {
|
||||
setPrompt(prompt: string, length: number): void;
|
||||
prompt(preserveCursor?: boolean): void;
|
||||
question(query: string, callback: Function): void;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
close(): void;
|
||||
write(data: any, key?: any): void;
|
||||
}
|
||||
export interface ReadLineOptions {
|
||||
input: NodeJS.ReadableStream;
|
||||
output: NodeJS.WritableStream;
|
||||
completer?: Function;
|
||||
terminal?: boolean;
|
||||
}
|
||||
|
||||
export interface ReadLine {
|
||||
createInterface(options: ReadLineOptions): ReadLineInstance;
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
module events {
|
||||
export class EventEmitter implements NodeJS.EventEmitter {
|
||||
static listenerCount(emitter: EventEmitter, event: string): number;
|
||||
|
||||
addListener(event: string, listener: Function): EventEmitter;
|
||||
on(event: string, listener: Function): EventEmitter;
|
||||
once(event: string, listener: Function): EventEmitter;
|
||||
removeListener(event: string, listener: Function): EventEmitter;
|
||||
removeAllListeners(event?: string): EventEmitter;
|
||||
setMaxListeners(n: number): void;
|
||||
listeners(event: string): Function[];
|
||||
emit(event: string, ...args: any[]): boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
module stream {
|
||||
|
||||
export interface Stream extends events.EventEmitter {
|
||||
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T;
|
||||
}
|
||||
|
||||
export interface ReadableOptions {
|
||||
highWaterMark?: number;
|
||||
encoding?: string;
|
||||
objectMode?: boolean;
|
||||
}
|
||||
|
||||
export class Readable extends events.EventEmitter implements NodeJS.ReadableStream {
|
||||
readable: boolean;
|
||||
constructor(opts?: ReadableOptions);
|
||||
_read(size: number): void;
|
||||
read(size?: number): any;
|
||||
setEncoding(encoding: string): void;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T;
|
||||
unpipe<T extends NodeJS.WritableStream>(destination?: T): void;
|
||||
unshift(chunk: string): void;
|
||||
unshift(chunk: Buffer): void;
|
||||
wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream;
|
||||
push(chunk: any, encoding?: string): boolean;
|
||||
}
|
||||
|
||||
export interface WritableOptions {
|
||||
highWaterMark?: number;
|
||||
decodeStrings?: boolean;
|
||||
}
|
||||
|
||||
export class Writable extends events.EventEmitter implements NodeJS.WritableStream {
|
||||
writable: boolean;
|
||||
constructor(opts?: WritableOptions);
|
||||
_write(data: Buffer, encoding: string, callback: Function): void;
|
||||
_write(data: string, encoding: string, callback: Function): void;
|
||||
write(buffer: Buffer, cb?: Function): boolean;
|
||||
write(str: string, cb?: Function): boolean;
|
||||
write(str: string, encoding?: string, cb?: Function): boolean;
|
||||
end(): void;
|
||||
end(buffer: Buffer, cb?: Function): void;
|
||||
end(str: string, cb?: Function): void;
|
||||
end(str: string, encoding?: string, cb?: Function): void;
|
||||
}
|
||||
|
||||
export interface DuplexOptions extends ReadableOptions, WritableOptions {
|
||||
allowHalfOpen?: boolean;
|
||||
}
|
||||
|
||||
// Note: Duplex extends both Readable and Writable.
|
||||
export class Duplex extends Readable implements NodeJS.ReadWriteStream {
|
||||
writable: boolean;
|
||||
constructor(opts?: DuplexOptions);
|
||||
_write(data: Buffer, encoding: string, callback: Function): void;
|
||||
_write(data: string, encoding: string, callback: Function): void;
|
||||
write(buffer: Buffer, cb?: Function): boolean;
|
||||
write(str: string, cb?: Function): boolean;
|
||||
write(str: string, encoding?: string, cb?: Function): boolean;
|
||||
end(): void;
|
||||
end(buffer: Buffer, cb?: Function): void;
|
||||
end(str: string, cb?: Function): void;
|
||||
end(str: string, encoding?: string, cb?: Function): void;
|
||||
}
|
||||
|
||||
export interface TransformOptions extends ReadableOptions, WritableOptions { }
|
||||
|
||||
// Note: Transform lacks the _read and _write methods of Readable/Writable.
|
||||
export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream {
|
||||
readable: boolean;
|
||||
writable: boolean;
|
||||
constructor(opts?: TransformOptions);
|
||||
_transform(chunk: Buffer, encoding: string, callback: Function): void;
|
||||
_transform(chunk: string, encoding: string, callback: Function): void;
|
||||
_flush(callback: Function): void;
|
||||
read(size?: number): any;
|
||||
setEncoding(encoding: string): void;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean; }): T;
|
||||
unpipe<T extends NodeJS.WritableStream>(destination?: T): void;
|
||||
unshift(chunk: string): void;
|
||||
unshift(chunk: Buffer): void;
|
||||
wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream;
|
||||
push(chunk: any, encoding?: string): boolean;
|
||||
write(buffer: Buffer, cb?: Function): boolean;
|
||||
write(str: string, cb?: Function): boolean;
|
||||
write(str: string, encoding?: string, cb?: Function): boolean;
|
||||
end(): void;
|
||||
end(buffer: Buffer, cb?: Function): void;
|
||||
end(str: string, cb?: Function): void;
|
||||
end(str: string, encoding?: string, cb?: Function): void;
|
||||
}
|
||||
|
||||
export class PassThrough extends Transform { }
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
module fs {
|
||||
interface Stats {
|
||||
isFile(): boolean;
|
||||
isDirectory(): boolean;
|
||||
isBlockDevice(): boolean;
|
||||
isCharacterDevice(): boolean;
|
||||
isSymbolicLink(): boolean;
|
||||
isFIFO(): boolean;
|
||||
isSocket(): boolean;
|
||||
dev: number;
|
||||
ino: number;
|
||||
mode: number;
|
||||
nlink: number;
|
||||
uid: number;
|
||||
gid: number;
|
||||
rdev: number;
|
||||
size: number;
|
||||
blksize: number;
|
||||
blocks: number;
|
||||
atime: Date;
|
||||
mtime: Date;
|
||||
ctime: Date;
|
||||
}
|
||||
interface FSWatcher extends events.EventEmitter {
|
||||
close(): void;
|
||||
}
|
||||
|
||||
export interface ReadStream extends stream.Readable { }
|
||||
export interface WriteStream extends stream.Writable { }
|
||||
|
||||
export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function renameSync(oldPath: string, newPath: string): void;
|
||||
export function truncate(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function truncate(path: string, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function truncateSync(path: string, len?: number): void;
|
||||
export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function ftruncateSync(fd: number, len?: number): void;
|
||||
export function chown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function chownSync(path: string, uid: number, gid: number): void;
|
||||
export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fchownSync(fd: number, uid: number, gid: number): void;
|
||||
export function lchown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function lchownSync(path: string, uid: number, gid: number): void;
|
||||
export function chmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function chmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function chmodSync(path: string, mode: number): void;
|
||||
export function chmodSync(path: string, mode: string): void;
|
||||
export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fchmodSync(fd: number, mode: number): void;
|
||||
export function fchmodSync(fd: number, mode: string): void;
|
||||
export function lchmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function lchmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function lchmodSync(path: string, mode: number): void;
|
||||
export function lchmodSync(path: string, mode: string): void;
|
||||
export function stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void;
|
||||
export function lstat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void;
|
||||
export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void;
|
||||
export function statSync(path: string): Stats;
|
||||
export function lstatSync(path: string): Stats;
|
||||
export function fstatSync(fd: number): Stats;
|
||||
export function link(srcpath: string, dstpath: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function linkSync(srcpath: string, dstpath: string): void;
|
||||
export function symlink(srcpath: string, dstpath: string, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function symlinkSync(srcpath: string, dstpath: string, type?: string): void;
|
||||
export function readlink(path: string, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void;
|
||||
export function readlinkSync(path: string): string;
|
||||
export function realpath(path: string, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void;
|
||||
export function realpath(path: string, cache: { [path: string]: string }, callback: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void;
|
||||
export function realpathSync(path: string, cache?: { [path: string]: string }): string;
|
||||
export function unlink(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function unlinkSync(path: string): void;
|
||||
export function rmdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function rmdirSync(path: string): void;
|
||||
export function mkdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function mkdir(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function mkdir(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function mkdirSync(path: string, mode?: number): void;
|
||||
export function mkdirSync(path: string, mode?: string): void;
|
||||
export function readdir(path: string, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void;
|
||||
export function readdirSync(path: string): string[];
|
||||
export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function closeSync(fd: number): void;
|
||||
export function open(path: string, flags: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void;
|
||||
export function open(path: string, flags: string, mode: number, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void;
|
||||
export function open(path: string, flags: string, mode: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void;
|
||||
export function openSync(path: string, flags: string, mode?: number): number;
|
||||
export function openSync(path: string, flags: string, mode?: string): number;
|
||||
export function utimes(path: string, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function utimes(path: string, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function utimesSync(path: string, atime: number, mtime: number): void;
|
||||
export function utimesSync(path: string, atime: Date, mtime: Date): void;
|
||||
export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function futimesSync(fd: number, atime: number, mtime: number): void;
|
||||
export function futimesSync(fd: number, atime: Date, mtime: Date): void;
|
||||
export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void;
|
||||
export function fsyncSync(fd: number): void;
|
||||
export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void;
|
||||
export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number;
|
||||
export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void;
|
||||
export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number;
|
||||
export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
|
||||
export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
|
||||
export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
|
||||
export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
|
||||
export function readFileSync(filename: string, encoding: string): string;
|
||||
export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string;
|
||||
export function readFileSync(filename: string, options?: { flag?: string; }): Buffer;
|
||||
export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
|
||||
export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void;
|
||||
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||
export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
|
||||
export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void;
|
||||
export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void;
|
||||
export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void;
|
||||
export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void;
|
||||
export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher;
|
||||
export function watch(filename: string, options: { persistent?: boolean; }, listener?: (event: string, filename: string) => any): FSWatcher;
|
||||
export function exists(path: string, callback?: (exists: boolean) => void): void;
|
||||
export function existsSync(path: string): boolean;
|
||||
export function createReadStream(path: string, options?: {
|
||||
flags?: string;
|
||||
encoding?: string;
|
||||
fd?: string;
|
||||
mode?: number;
|
||||
bufferSize?: number;
|
||||
}): ReadStream;
|
||||
export function createReadStream(path: string, options?: {
|
||||
flags?: string;
|
||||
encoding?: string;
|
||||
fd?: string;
|
||||
mode?: string;
|
||||
bufferSize?: number;
|
||||
}): ReadStream;
|
||||
export function createWriteStream(path: string, options?: {
|
||||
flags?: string;
|
||||
encoding?: string;
|
||||
string?: string;
|
||||
}): WriteStream;
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
module path {
|
||||
export function normalize(p: string): string;
|
||||
export function join(...paths: any[]): string;
|
||||
export function resolve(...pathSegments: any[]): string;
|
||||
export function relative(from: string, to: string): string;
|
||||
export function dirname(p: string): string;
|
||||
export function basename(p: string, ext?: string): string;
|
||||
export function extname(p: string): string;
|
||||
export var sep: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare module NodeJS {
|
||||
module _debugger {
|
||||
export interface Packet {
|
||||
raw: string;
|
||||
headers: string[];
|
||||
body: Message;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
seq: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface RequestInfo {
|
||||
command: string;
|
||||
arguments: any;
|
||||
}
|
||||
|
||||
export interface Request extends Message, RequestInfo {
|
||||
}
|
||||
|
||||
export interface Event extends Message {
|
||||
event: string;
|
||||
body?: any;
|
||||
}
|
||||
|
||||
export interface Response extends Message {
|
||||
request_seq: number;
|
||||
success: boolean;
|
||||
/** Contains error message if success == false. */
|
||||
message?: string;
|
||||
/** Contains message body if success == true. */
|
||||
body?: any;
|
||||
}
|
||||
|
||||
export interface BreakpointMessageBody {
|
||||
type: string;
|
||||
target: number;
|
||||
line: number;
|
||||
}
|
||||
|
||||
export class Protocol {
|
||||
res: Packet;
|
||||
state: string;
|
||||
execute(data: string): void;
|
||||
serialize(rq: Request): string;
|
||||
onResponse: (pkt: Packet) => void;
|
||||
}
|
||||
|
||||
export var NO_FRAME: number;
|
||||
export var port: number;
|
||||
|
||||
export interface ScriptDesc {
|
||||
name: string;
|
||||
id: number;
|
||||
isNative?: boolean;
|
||||
handle?: number;
|
||||
type: string;
|
||||
lineOffset?: number;
|
||||
columnOffset?: number;
|
||||
lineCount?: number;
|
||||
}
|
||||
|
||||
export interface Breakpoint {
|
||||
id: number;
|
||||
scriptId: number;
|
||||
script: ScriptDesc;
|
||||
line: number;
|
||||
condition?: string;
|
||||
scriptReq?: string;
|
||||
}
|
||||
|
||||
export interface RequestHandler {
|
||||
(err: boolean, body: Message, res: Packet): void;
|
||||
request_seq?: number;
|
||||
}
|
||||
|
||||
export interface ResponseBodyHandler {
|
||||
(err: boolean, body?: any): void;
|
||||
request_seq?: number;
|
||||
}
|
||||
|
||||
export interface ExceptionInfo {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface BreakResponse {
|
||||
script?: ScriptDesc;
|
||||
exception?: ExceptionInfo;
|
||||
sourceLine: number;
|
||||
sourceLineText: string;
|
||||
sourceColumn: number;
|
||||
}
|
||||
|
||||
export function SourceInfo(body: BreakResponse): string;
|
||||
|
||||
export class Client extends events.EventEmitter {
|
||||
protocol: Protocol;
|
||||
scripts: ScriptDesc[];
|
||||
handles: ScriptDesc[];
|
||||
breakpoints: Breakpoint[];
|
||||
currentSourceLine: number;
|
||||
currentSourceColumn: number;
|
||||
currentSourceLineText: string;
|
||||
currentFrame: number;
|
||||
currentScript: string;
|
||||
|
||||
connect(port: number, host: string): void;
|
||||
req(req: any, cb: RequestHandler): void;
|
||||
reqFrameEval(code: string, frame: number, cb: RequestHandler): void;
|
||||
mirrorObject(obj: any, depth: number, cb: ResponseBodyHandler): void;
|
||||
setBreakpoint(rq: BreakpointMessageBody, cb: RequestHandler): void;
|
||||
clearBreakpoint(rq: Request, cb: RequestHandler): void;
|
||||
listbreakpoints(cb: RequestHandler): void;
|
||||
reqSource(from: number, to: number, cb: RequestHandler): void;
|
||||
reqScripts(cb: any): void;
|
||||
reqContinue(cb: RequestHandler): void;
|
||||
}
|
||||
}
|
||||
}
|
823
src/server/protocol.d.ts
vendored
Normal file
823
src/server/protocol.d.ts
vendored
Normal file
|
@ -0,0 +1,823 @@
|
|||
/**
|
||||
* Declaration module describing the TypeScript Server protocol
|
||||
*/
|
||||
declare module ts.server.protocol {
|
||||
/**
|
||||
* A TypeScript Server message
|
||||
*/
|
||||
export interface Message {
|
||||
/**
|
||||
* Sequence number of the message
|
||||
*/
|
||||
seq: number;
|
||||
|
||||
/**
|
||||
* One of "request", "response", or "event"
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-initiated request message
|
||||
*/
|
||||
export interface Request extends Message {
|
||||
/**
|
||||
* The command to execute
|
||||
*/
|
||||
command: string;
|
||||
|
||||
/**
|
||||
* Object containing arguments for the command
|
||||
*/
|
||||
arguments?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-initiated event message
|
||||
*/
|
||||
export interface Event extends Message {
|
||||
/**
|
||||
* Name of event
|
||||
*/
|
||||
event: string;
|
||||
|
||||
/**
|
||||
* Event-specific information
|
||||
*/
|
||||
body?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response by server to client request message.
|
||||
*/
|
||||
export interface Response extends Message {
|
||||
/**
|
||||
* Sequence number of the request message.
|
||||
*/
|
||||
request_seq: number;
|
||||
|
||||
/**
|
||||
* Outcome of the request.
|
||||
*/
|
||||
success: boolean;
|
||||
|
||||
/**
|
||||
* The command requested.
|
||||
*/
|
||||
command: string;
|
||||
|
||||
/**
|
||||
* Contains error message if success == false.
|
||||
*/
|
||||
message?: string;
|
||||
|
||||
/**
|
||||
* Contains message body if success == true.
|
||||
*/
|
||||
body?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for FileRequest messages.
|
||||
*/
|
||||
export interface FileRequestArgs {
|
||||
/**
|
||||
* The file for the request (absolute pathname required).
|
||||
*/
|
||||
file: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request whose sole parameter is a file name.
|
||||
*/
|
||||
export interface FileRequest extends Request {
|
||||
arguments: FileRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instances of this interface specify a location in a source file:
|
||||
* (file, line, col), where line and column are 1-based.
|
||||
*/
|
||||
export interface FileLocationRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* The line number for the request (1-based).
|
||||
*/
|
||||
line: number;
|
||||
|
||||
/**
|
||||
* The column for the request (1-based).
|
||||
*/
|
||||
col: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A request whose arguments specify a file location (file, line, col).
|
||||
*/
|
||||
export interface FileLocationRequest extends FileRequest {
|
||||
arguments: FileLocationRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to definition request; value of command field is
|
||||
* "definition". Return response giving the file locations that
|
||||
* define the symbol found in file at location line, col.
|
||||
*/
|
||||
export interface DefinitionRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Location in source code expressed as (one-based) line and column.
|
||||
*/
|
||||
export interface Location {
|
||||
line: number;
|
||||
col: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object found in response messages defining a span of text in source code.
|
||||
*/
|
||||
export interface TextSpan {
|
||||
/**
|
||||
* First character of the definition.
|
||||
*/
|
||||
start: Location;
|
||||
|
||||
/**
|
||||
* One character past last character of the definition.
|
||||
*/
|
||||
end: Location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object found in response messages defining a span of text in a specific source file.
|
||||
*/
|
||||
export interface FileSpan extends TextSpan {
|
||||
/**
|
||||
* File containing text span.
|
||||
*/
|
||||
file: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition response message. Gives text range for definition.
|
||||
*/
|
||||
export interface DefinitionResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find references request; value of command field is
|
||||
* "references". Return response giving the file locations that
|
||||
* reference the symbol found in file at location line, col.
|
||||
*/
|
||||
export interface ReferencesRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
export interface ReferencesResponseItem extends FileSpan {
|
||||
/** Text of line containing the reference. Including this
|
||||
* with the response avoids latency of editor loading files
|
||||
* to show text of reference line (the server already has
|
||||
* loaded the referencing files).
|
||||
*/
|
||||
lineText: string;
|
||||
|
||||
/**
|
||||
* True if reference is a write location, false otherwise.
|
||||
*/
|
||||
isWriteAccess: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The body of a "references" response message.
|
||||
*/
|
||||
export interface ReferencesResponseBody {
|
||||
/**
|
||||
* The file locations referencing the symbol.
|
||||
*/
|
||||
refs: ReferencesResponseItem[];
|
||||
|
||||
/**
|
||||
* The name of the symbol.
|
||||
*/
|
||||
symbolName: string;
|
||||
|
||||
/**
|
||||
* The start column of the symbol (on the line provided by the references request).
|
||||
*/
|
||||
symbolStartCol: number;
|
||||
|
||||
/**
|
||||
* The full display name of the symbol.
|
||||
*/
|
||||
symbolDisplayString: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to "references" request.
|
||||
*/
|
||||
export interface ReferencesResponse extends Response {
|
||||
body?: ReferencesResponseBody;
|
||||
}
|
||||
|
||||
export interface RenameRequestArgs extends FileLocationRequestArgs {
|
||||
findInComments?: boolean;
|
||||
findInStrings?: boolean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rename request; value of command field is "rename". Return
|
||||
* response giving the file locations that reference the symbol
|
||||
* found in file at location line, col. Also return full display
|
||||
* name of the symbol so that client can print it unambiguously.
|
||||
*/
|
||||
export interface RenameRequest extends FileLocationRequest {
|
||||
arguments: RenameRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the item to be renamed.
|
||||
*/
|
||||
export interface RenameInfo {
|
||||
/**
|
||||
* True if item can be renamed.
|
||||
*/
|
||||
canRename: boolean;
|
||||
|
||||
/**
|
||||
* Error message if item can not be renamed.
|
||||
*/
|
||||
localizedErrorMessage?: string;
|
||||
|
||||
/**
|
||||
* Display name of the item to be renamed.
|
||||
*/
|
||||
displayName: string;
|
||||
|
||||
/**
|
||||
* Full display name of item to be renamed.
|
||||
*/
|
||||
fullDisplayName: string;
|
||||
|
||||
/**
|
||||
* The items's kind (such as 'className' or 'parameterName' or plain 'text').
|
||||
*/
|
||||
kind: string;
|
||||
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A group of text spans, all in 'file'.
|
||||
*/
|
||||
export interface SpanGroup {
|
||||
/** The file to which the spans apply */
|
||||
file: string;
|
||||
/** The text spans in this group */
|
||||
locs: TextSpan[];
|
||||
}
|
||||
|
||||
export interface RenameResponseBody {
|
||||
/**
|
||||
* Information about the item to be renamed.
|
||||
*/
|
||||
info: RenameInfo;
|
||||
|
||||
/**
|
||||
* An array of span groups (one per file) that refer to the item to be renamed.
|
||||
*/
|
||||
locs: SpanGroup[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename response message.
|
||||
*/
|
||||
export interface RenameResponse extends Response {
|
||||
body?: RenameResponseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open request; value of command field is "open". Notify the
|
||||
* server that the client has file open. The server will not
|
||||
* monitor the filesystem for changes in this file and will assume
|
||||
* that the client is updating the server (using the change and/or
|
||||
* reload messages) when the file changes. Server does not currently
|
||||
* send a response to an open request.
|
||||
*/
|
||||
export interface OpenRequest extends FileRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close request; value of command field is "close". Notify the
|
||||
* server that the client has closed a previously open file. If
|
||||
* file is still referenced by open files, the server will resume
|
||||
* monitoring the filesystem for changes to file. Server does not
|
||||
* currently send a response to a close request.
|
||||
*/
|
||||
export interface CloseRequest extends FileRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickinfo request; value of command field is
|
||||
* "quickinfo". Return response giving a quick type and
|
||||
* documentation string for the symbol found in file at location
|
||||
* line, col.
|
||||
*/
|
||||
export interface QuickInfoRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Body of QuickInfoResponse.
|
||||
*/
|
||||
export interface QuickInfoResponseBody {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName' or plain 'text').
|
||||
*/
|
||||
kind: string;
|
||||
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers: string;
|
||||
|
||||
/**
|
||||
* Starting file location of symbol.
|
||||
*/
|
||||
start: Location;
|
||||
|
||||
/**
|
||||
* One past last character of symbol.
|
||||
*/
|
||||
end: Location;
|
||||
|
||||
/**
|
||||
* Type and kind of symbol.
|
||||
*/
|
||||
displayString: string;
|
||||
|
||||
/**
|
||||
* Documentation associated with symbol.
|
||||
*/
|
||||
documentation: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickinfo response message.
|
||||
*/
|
||||
export interface QuickInfoResponse extends Response {
|
||||
body?: QuickInfoResponseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for format messages.
|
||||
*/
|
||||
export interface FormatRequestArgs extends FileLocationRequestArgs {
|
||||
/**
|
||||
* Last line of range for which to format text in file.
|
||||
*/
|
||||
endLine: number;
|
||||
|
||||
/**
|
||||
* Last column of range for which to format text in file.
|
||||
*/
|
||||
endCol: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format request; value of command field is "format". Return
|
||||
* response giving zero or more edit instructions. The edit
|
||||
* instructions will be sorted in file order. Applying the edit
|
||||
* instructions in reverse to file will result in correctly
|
||||
* reformatted text.
|
||||
*/
|
||||
export interface FormatRequest extends FileLocationRequest {
|
||||
arguments: FormatRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object found in response messages defining an editing
|
||||
* instruction for a span of text in source code. The effect of
|
||||
* this instruction is to replace the text starting at start and
|
||||
* ending one character before end with newText. For an insertion,
|
||||
* the text span is empty. For a deletion, newText is empty.
|
||||
*/
|
||||
export interface CodeEdit {
|
||||
/**
|
||||
* First character of the text span to edit.
|
||||
*/
|
||||
start: Location;
|
||||
|
||||
/**
|
||||
* One character past last character of the text span to edit.
|
||||
*/
|
||||
end: Location;
|
||||
|
||||
/**
|
||||
* Replace the span defined above with this string (may be
|
||||
* the empty string).
|
||||
*/
|
||||
newText: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and format on key response message.
|
||||
*/
|
||||
export interface FormatResponse extends Response {
|
||||
body?: CodeEdit[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for format on key messages.
|
||||
*/
|
||||
export interface FormatOnKeyRequestArgs extends FileLocationRequestArgs {
|
||||
/**
|
||||
* Key pressed (';', '\n', or '}').
|
||||
*/
|
||||
key: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format on key request; value of command field is
|
||||
* "formatonkey". Given file location and key typed (as string),
|
||||
* return response giving zero or more edit instructions. The
|
||||
* edit instructions will be sorted in file order. Applying the
|
||||
* edit instructions in reverse to file will result in correctly
|
||||
* reformatted text.
|
||||
*/
|
||||
export interface FormatOnKeyRequest extends FileLocationRequest {
|
||||
arguments: FormatOnKeyRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for completions messages.
|
||||
*/
|
||||
export interface CompletionsRequestArgs extends FileLocationRequestArgs {
|
||||
/**
|
||||
* Optional prefix to apply to possible completions.
|
||||
*/
|
||||
prefix?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completions request; value of command field is "completions".
|
||||
* Given a file location (file, line, col) and a prefix (which may
|
||||
* be the empty string), return the possible completions that
|
||||
* begin with prefix.
|
||||
*/
|
||||
export interface CompletionsRequest extends FileLocationRequest {
|
||||
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.
|
||||
*/
|
||||
export interface SymbolDisplayPart {
|
||||
/**
|
||||
* Text of an item describing the symbol.
|
||||
*/
|
||||
text: string;
|
||||
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName' or plain 'text').
|
||||
*/
|
||||
kind: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item found in a completion response.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional completion entry details, available on demand
|
||||
*/
|
||||
export interface CompletionEntryDetails extends CompletionEntry {
|
||||
/**
|
||||
* Display parts of the symbol (similar to quick info).
|
||||
*/
|
||||
displayParts: SymbolDisplayPart[];
|
||||
|
||||
/**
|
||||
* Documentation strings for the symbol.
|
||||
*/
|
||||
documentation: SymbolDisplayPart[];
|
||||
}
|
||||
|
||||
export interface CompletionsResponse extends Response {
|
||||
body?: CompletionEntry[];
|
||||
}
|
||||
|
||||
export interface CompletionDetailsResponse extends Response {
|
||||
body?: CompletionEntryDetails[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for geterr messages.
|
||||
*/
|
||||
export interface GeterrRequestArgs {
|
||||
/**
|
||||
* List of file names for which to compute compiler errors.
|
||||
* The files will be checked in list order.
|
||||
*/
|
||||
files: string[];
|
||||
|
||||
/**
|
||||
* Delay in milliseconds to wait before starting to compute
|
||||
* errors for the files in the file list
|
||||
*/
|
||||
delay: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geterr request; value of command field is "geterr". Wait for
|
||||
* delay milliseconds and then, if during the wait no change or
|
||||
* reload messages have arrived for the first file in the files
|
||||
* list, get the syntactic errors for the file, field requests,
|
||||
* and then get the semantic errors for the file. Repeat with a
|
||||
* smaller delay for each subsequent file on the files list. Best
|
||||
* practice for an editor is to send a file list containing each
|
||||
* file that is currently visible, in most-recently-used order.
|
||||
*/
|
||||
export interface GeterrRequest extends Request {
|
||||
arguments: GeterrRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Item of diagnostic information found in a DiagnosticEvent message.
|
||||
*/
|
||||
export interface Diagnostic {
|
||||
/**
|
||||
* Starting file location at which text appies.
|
||||
*/
|
||||
start: Location;
|
||||
|
||||
/**
|
||||
* The last file location at which the text applies.
|
||||
*/
|
||||
end: Location;
|
||||
|
||||
/**
|
||||
* Text of diagnostic message.
|
||||
*/
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface DiagnosticEventBody {
|
||||
/**
|
||||
* The file for which diagnostic information is reported.
|
||||
*/
|
||||
file: string;
|
||||
|
||||
/**
|
||||
* An array of diagnostic information items.
|
||||
*/
|
||||
diagnostics: Diagnostic[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Event message for "syntaxDiag" and "semanticDiag" event types.
|
||||
* These events provide syntactic and semantic errors for a file.
|
||||
*/
|
||||
export interface DiagnosticEvent extends Event {
|
||||
body?: DiagnosticEventBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for reload request.
|
||||
*/
|
||||
export interface ReloadRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* Name of temporary file from which to reload file
|
||||
* contents. May be same as file.
|
||||
*/
|
||||
tmpfile: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload request message; value of command field is "reload".
|
||||
* Reload contents of file with name given by the 'file' argument
|
||||
* from temporary file with name given by the 'tmpfile' argument.
|
||||
* The two names can be identical.
|
||||
*/
|
||||
export interface ReloadRequest extends FileRequest {
|
||||
arguments: ReloadRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to "reload" request. This is just an acknowledgement, so
|
||||
* no body field is required.
|
||||
*/
|
||||
export interface ReloadResponse extends Response {
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for saveto request.
|
||||
*/
|
||||
export interface SavetoRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* Name of temporary file into which to save server's view of
|
||||
* file contents.
|
||||
*/
|
||||
tmpfile: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saveto request message; value of command field is "saveto".
|
||||
* For debugging purposes, save to a temporaryfile (named by
|
||||
* argument 'tmpfile') the contents of file named by argument
|
||||
* 'file'. The server does not currently send a response to a
|
||||
* "saveto" request.
|
||||
*/
|
||||
export interface SavetoRequest extends FileRequest {
|
||||
arguments: SavetoRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for navto request message.
|
||||
*/
|
||||
export interface NavtoRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* Search term to navigate to from current location; term can
|
||||
* be '.*' or an identifier prefix.
|
||||
*/
|
||||
searchTerm: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Navto request message; value of command field is "navto".
|
||||
* Return list of objects giving file locations and symbols that
|
||||
* match the search term given in argument 'searchTerm'. The
|
||||
* context for the search is given by the named file.
|
||||
*/
|
||||
export interface NavtoRequest extends FileRequest {
|
||||
arguments: NavtoRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* An item found in a navto response.
|
||||
*/
|
||||
export interface NavtoItem {
|
||||
/**
|
||||
* The symbol's name.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
|
||||
/**
|
||||
* exact, substring, or prefix.
|
||||
*/
|
||||
matchKind?: string;
|
||||
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers?: string;
|
||||
|
||||
/**
|
||||
* The file in which the symbol is found.
|
||||
*/
|
||||
file: string;
|
||||
|
||||
/**
|
||||
* The location within file at which the symbol is found.
|
||||
*/
|
||||
start: Location;
|
||||
|
||||
/**
|
||||
* One past the last character of the symbol.
|
||||
*/
|
||||
end: Location;
|
||||
|
||||
/**
|
||||
* Name of symbol's container symbol (if any); for example,
|
||||
* the class name if symbol is a class member.
|
||||
*/
|
||||
containerName?: string;
|
||||
|
||||
/**
|
||||
* Kind of symbol's container symbol (if any).
|
||||
*/
|
||||
containerKind?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Navto response message. Body is an array of navto items. Each
|
||||
* item gives a symbol that matched the search term.
|
||||
*/
|
||||
export interface NavtoResponse extends Response {
|
||||
body?: NavtoItem[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for change request message.
|
||||
*/
|
||||
export interface ChangeRequestArgs extends FormatRequestArgs {
|
||||
/**
|
||||
* Optional string to insert at location (file, line, col).
|
||||
*/
|
||||
insertString?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change request message; value of command field is "change".
|
||||
* Update the server's view of the file named by argument 'file'.
|
||||
* Server does not currently send a response to a change request.
|
||||
*/
|
||||
export interface ChangeRequest extends FileLocationRequest {
|
||||
arguments: ChangeRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to "brace" request.
|
||||
*/
|
||||
export interface BraceResponse extends Response {
|
||||
body?: TextSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Brace matching request; value of command field is "brace".
|
||||
* Return response giving the file locations of matching braces
|
||||
* found in file at location line, col.
|
||||
*/
|
||||
export interface BraceRequest extends FileLocationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* NavBar itesm request; value of command field is "navbar".
|
||||
* Return response giving the list of navigation bar entries
|
||||
* extracted from the requested file.
|
||||
*/
|
||||
export interface NavBarRequest extends FileRequest {
|
||||
}
|
||||
|
||||
export interface NavigationBarItem {
|
||||
/**
|
||||
* The item's display text.
|
||||
*/
|
||||
text: string;
|
||||
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
kindModifiers?: string;
|
||||
|
||||
/**
|
||||
* The definition locations of the item.
|
||||
*/
|
||||
spans: TextSpan[];
|
||||
|
||||
/**
|
||||
* Optional children.
|
||||
*/
|
||||
childItems?: NavigationBarItem[];
|
||||
}
|
||||
|
||||
export interface NavBarResponse extends Response {
|
||||
body?: NavigationBarItem[];
|
||||
}
|
||||
}
|
219
src/server/server.ts
Normal file
219
src/server/server.ts
Normal file
|
@ -0,0 +1,219 @@
|
|||
/// <reference path="node.d.ts" />
|
||||
/// <reference path="session.ts" />
|
||||
|
||||
module ts.server {
|
||||
var nodeproto: typeof NodeJS._debugger = require('_debugger');
|
||||
var readline: NodeJS.ReadLine = require('readline');
|
||||
var path: NodeJS.Path = require('path');
|
||||
var fs: typeof NodeJS.fs = require('fs');
|
||||
|
||||
var rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
terminal: false,
|
||||
});
|
||||
|
||||
class Logger implements ts.server.Logger {
|
||||
fd = -1;
|
||||
seq = 0;
|
||||
inGroup = false;
|
||||
firstInGroup = true;
|
||||
|
||||
constructor(public logFilename: string) {
|
||||
}
|
||||
|
||||
static padStringRight(str: string, padding: string) {
|
||||
return (str + padding).slice(0, padding.length);
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.fd >= 0) {
|
||||
fs.close(this.fd);
|
||||
}
|
||||
}
|
||||
|
||||
perftrc(s: string) {
|
||||
this.msg(s, "Perf");
|
||||
}
|
||||
|
||||
info(s: string) {
|
||||
this.msg(s, "Info");
|
||||
}
|
||||
|
||||
startGroup() {
|
||||
this.inGroup = true;
|
||||
this.firstInGroup = true;
|
||||
}
|
||||
|
||||
endGroup() {
|
||||
this.inGroup = false;
|
||||
this.seq++;
|
||||
this.firstInGroup = true;
|
||||
}
|
||||
|
||||
msg(s: string, type = "Err") {
|
||||
if (this.fd < 0) {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
if (this.fd >= 0) {
|
||||
s = s + "\n";
|
||||
var prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
|
||||
if (this.firstInGroup) {
|
||||
s = prefix + s;
|
||||
this.firstInGroup = false;
|
||||
}
|
||||
if (!this.inGroup) {
|
||||
this.seq++;
|
||||
this.firstInGroup = true;
|
||||
}
|
||||
var buf = new Buffer(s);
|
||||
fs.writeSync(this.fd, buf, 0, buf.length, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface WatchedFile {
|
||||
fileName: string;
|
||||
callback: (fileName: string) => void;
|
||||
mtime: Date;
|
||||
}
|
||||
|
||||
class WatchedFileSet {
|
||||
private watchedFiles: WatchedFile[] = [];
|
||||
private nextFileToCheck = 0;
|
||||
private watchTimer: NodeJS.Timer;
|
||||
private static fileDeleted = 34;
|
||||
|
||||
// average async stat takes about 30 microseconds
|
||||
// set chunk size to do 30 files in < 1 millisecond
|
||||
constructor(public interval = 2500, public chunkSize = 30) {
|
||||
}
|
||||
|
||||
private static copyListRemovingItem<T>(item: T, list: T[]) {
|
||||
var copiedList: T[] = [];
|
||||
for (var i = 0, len = list.length; i < len; i++) {
|
||||
if (list[i] != item) {
|
||||
copiedList.push(list[i]);
|
||||
}
|
||||
}
|
||||
return copiedList;
|
||||
}
|
||||
|
||||
private static getModifiedTime(fileName: string): Date {
|
||||
return fs.statSync(fileName).mtime;
|
||||
}
|
||||
|
||||
private poll(checkedIndex: number) {
|
||||
var watchedFile = this.watchedFiles[checkedIndex];
|
||||
if (!watchedFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat(watchedFile.fileName,(err, stats) => {
|
||||
if (err) {
|
||||
var msg = err.message;
|
||||
if (err.errno) {
|
||||
msg += " errno: " + err.errno.toString();
|
||||
}
|
||||
if (err.errno == WatchedFileSet.fileDeleted) {
|
||||
watchedFile.callback(watchedFile.fileName);
|
||||
}
|
||||
}
|
||||
else if (watchedFile.mtime.getTime() != stats.mtime.getTime()) {
|
||||
watchedFile.mtime = WatchedFileSet.getModifiedTime(watchedFile.fileName);
|
||||
watchedFile.callback(watchedFile.fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this implementation uses polling and
|
||||
// stat due to inconsistencies of fs.watch
|
||||
// and efficiency of stat on modern filesystems
|
||||
private startWatchTimer() {
|
||||
this.watchTimer = setInterval(() => {
|
||||
var count = 0;
|
||||
var nextToCheck = this.nextFileToCheck;
|
||||
var firstCheck = -1;
|
||||
while ((count < this.chunkSize) && (nextToCheck != firstCheck)) {
|
||||
this.poll(nextToCheck);
|
||||
if (firstCheck < 0) {
|
||||
firstCheck = nextToCheck;
|
||||
}
|
||||
nextToCheck++;
|
||||
if (nextToCheck === this.watchedFiles.length) {
|
||||
nextToCheck = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
this.nextFileToCheck = nextToCheck;
|
||||
}, this.interval);
|
||||
}
|
||||
|
||||
addFile(fileName: string, callback: (fileName: string) => void ): WatchedFile {
|
||||
var file: WatchedFile = {
|
||||
fileName,
|
||||
callback,
|
||||
mtime: WatchedFileSet.getModifiedTime(fileName)
|
||||
};
|
||||
|
||||
this.watchedFiles.push(file);
|
||||
if (this.watchedFiles.length === 1) {
|
||||
this.startWatchTimer();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
removeFile(file: WatchedFile) {
|
||||
this.watchedFiles = WatchedFileSet.copyListRemovingItem(file, this.watchedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
class IOSession extends Session {
|
||||
constructor(host: ServerHost, logger: ts.server.Logger) {
|
||||
super(host, logger);
|
||||
}
|
||||
|
||||
listen() {
|
||||
rl.on('line',(input: string) => {
|
||||
var message = input.trim();
|
||||
this.onMessage(message);
|
||||
});
|
||||
|
||||
rl.on('close',() => {
|
||||
this.projectService.closeLog();
|
||||
this.projectService.log("Exiting...");
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
var logger = new Logger(__dirname + "/.log" + process.pid.toString());
|
||||
|
||||
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
// on all os and with network mounted files.
|
||||
// For 90 referenced files, the average time to detect
|
||||
// changes is 2*msInterval (by default 5 seconds).
|
||||
// The overhead of this is .04 percent (1/2500) with
|
||||
// average pause of < 1 millisecond (and max
|
||||
// pause less than 1.5 milliseconds); question is
|
||||
// do we anticipate reference sets in the 100s and
|
||||
// do we care about waiting 10-20 seconds to detect
|
||||
// changes for large reference sets? If so, do we want
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
var watchedFileSet = new WatchedFileSet();
|
||||
ts.sys.watchFile = function (fileName, callback) {
|
||||
var watchedFile = watchedFileSet.addFile(fileName, callback);
|
||||
return {
|
||||
close: () => watchedFileSet.removeFile(watchedFile)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Start listening
|
||||
new IOSession(ts.sys, logger).listen();
|
||||
}
|
801
src/server/session.ts
Normal file
801
src/server/session.ts
Normal file
|
@ -0,0 +1,801 @@
|
|||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="node.d.ts" />
|
||||
/// <reference path="protocol.d.ts" />
|
||||
/// <reference path="editorServices.ts" />
|
||||
|
||||
module ts.server {
|
||||
var spaceCache = [" ", " ", " ", " "];
|
||||
|
||||
interface StackTraceError extends Error {
|
||||
stack?: string;
|
||||
}
|
||||
|
||||
function generateSpaces(n: number): string {
|
||||
if (!spaceCache[n]) {
|
||||
var strBuilder = "";
|
||||
for (var i = 0; i < n; i++) {
|
||||
strBuilder += " ";
|
||||
}
|
||||
spaceCache[n] = strBuilder;
|
||||
}
|
||||
return spaceCache[n];
|
||||
}
|
||||
|
||||
interface FileStart {
|
||||
file: string;
|
||||
start: ILineInfo;
|
||||
}
|
||||
|
||||
function compareNumber(a: number, b: number) {
|
||||
if (a < b) {
|
||||
return -1;
|
||||
}
|
||||
else if (a == b) {
|
||||
return 0;
|
||||
}
|
||||
else return 1;
|
||||
}
|
||||
|
||||
function compareFileStart(a: FileStart, b: FileStart) {
|
||||
if (a.file < b.file) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.file == b.file) {
|
||||
var n = compareNumber(a.start.line, b.start.line);
|
||||
if (n == 0) {
|
||||
return compareNumber(a.start.col, b.start.col);
|
||||
}
|
||||
else return n;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
function sortNavItems(items: ts.NavigateToItem[]) {
|
||||
return items.sort((a, b) => {
|
||||
if (a.matchKind < b.matchKind) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.matchKind == b.matchKind) {
|
||||
var lowa = a.name.toLowerCase();
|
||||
var lowb = b.name.toLowerCase();
|
||||
if (lowa < lowb) {
|
||||
return -1;
|
||||
}
|
||||
else if (lowa == lowb) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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),
|
||||
text: ts.flattenDiagnosticMessageText(diag.messageText, "\n")
|
||||
};
|
||||
}
|
||||
|
||||
interface PendingErrorCheck {
|
||||
fileName: string;
|
||||
project: Project;
|
||||
}
|
||||
|
||||
function allEditsBeforePos(edits: ts.TextChange[], pos: number) {
|
||||
for (var i = 0, len = edits.length; i < len; i++) {
|
||||
if (ts.textSpanEnd(edits[i].span) >= pos) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export module CommandNames {
|
||||
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";
|
||||
export var Geterr = "geterr";
|
||||
export var NavBar = "navbar";
|
||||
export var Navto = "navto";
|
||||
export var Open = "open";
|
||||
export var Quickinfo = "quickinfo";
|
||||
export var References = "references";
|
||||
export var Reload = "reload";
|
||||
export var Rename = "rename";
|
||||
export var Saveto = "saveto";
|
||||
export var Brace = "brace";
|
||||
export var Unknown = "unknown";
|
||||
}
|
||||
|
||||
module Errors {
|
||||
export var NoProject = new Error("No Project.");
|
||||
export var NoContent = new Error("No Content.");
|
||||
}
|
||||
|
||||
export interface ServerHost extends ts.System {
|
||||
}
|
||||
|
||||
export class Session {
|
||||
projectService: ProjectService;
|
||||
pendingOperation = false;
|
||||
fileHash: ts.Map<number> = {};
|
||||
nextFileId = 1;
|
||||
errorTimer: NodeJS.Timer;
|
||||
immediateId: any;
|
||||
changeSeq = 0;
|
||||
|
||||
constructor(private host: ServerHost, private logger: Logger) {
|
||||
this.projectService = new ProjectService(host, logger);
|
||||
}
|
||||
|
||||
logError(err: Error, cmd: string) {
|
||||
var typedErr = <StackTraceError>err;
|
||||
var msg = "Exception on executing command " + cmd;
|
||||
if (typedErr.message) {
|
||||
msg += ":\n" + typedErr.message;
|
||||
if (typedErr.stack) {
|
||||
msg += "\n" + typedErr.stack;
|
||||
}
|
||||
}
|
||||
this.projectService.log(msg);
|
||||
}
|
||||
|
||||
sendLineToClient(line: string) {
|
||||
this.host.write(line + this.host.newLine);
|
||||
}
|
||||
|
||||
send(msg: NodeJS._debugger.Message) {
|
||||
var json = JSON.stringify(msg);
|
||||
this.sendLineToClient('Content-Length: ' + (1 + Buffer.byteLength(json, 'utf8')) +
|
||||
'\r\n\r\n' + json);
|
||||
}
|
||||
|
||||
event(info: any, eventName: string) {
|
||||
var ev: NodeJS._debugger.Event = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: eventName,
|
||||
body: info,
|
||||
};
|
||||
this.send(ev);
|
||||
}
|
||||
|
||||
response(info: any, cmdName: string, reqSeq = 0, errorMsg?: string) {
|
||||
var res: protocol.Response = {
|
||||
seq: 0,
|
||||
type: "response",
|
||||
command: cmdName,
|
||||
request_seq: reqSeq,
|
||||
success: !errorMsg,
|
||||
}
|
||||
if (!errorMsg) {
|
||||
res.body = info;
|
||||
}
|
||||
else {
|
||||
res.message = errorMsg;
|
||||
}
|
||||
this.send(res);
|
||||
}
|
||||
|
||||
output(body: any, commandName: string, requestSequence = 0, errorMessage?: string) {
|
||||
this.response(body, commandName, requestSequence, errorMessage);
|
||||
}
|
||||
|
||||
semanticCheck(file: string, project: Project) {
|
||||
var diags = project.compilerService.languageService.getSemanticDiagnostics(file);
|
||||
if (diags) {
|
||||
var bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
|
||||
this.event({ file: file, diagnostics: bakedDiags }, "semanticDiag");
|
||||
}
|
||||
}
|
||||
|
||||
syntacticCheck(file: string, project: Project) {
|
||||
var diags = project.compilerService.languageService.getSyntacticDiagnostics(file);
|
||||
if (diags) {
|
||||
var bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
|
||||
this.event({ file: file, diagnostics: bakedDiags }, "syntaxDiag");
|
||||
}
|
||||
}
|
||||
|
||||
errorCheck(file: string, project: Project) {
|
||||
this.syntacticCheck(file, project);
|
||||
this.semanticCheck(file, project);
|
||||
}
|
||||
|
||||
updateErrorCheck(checkList: PendingErrorCheck[], seq: number,
|
||||
matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200) {
|
||||
if (followMs > ms) {
|
||||
followMs = ms;
|
||||
}
|
||||
if (this.errorTimer) {
|
||||
clearTimeout(this.errorTimer);
|
||||
}
|
||||
if (this.immediateId) {
|
||||
clearImmediate(this.immediateId);
|
||||
this.immediateId = undefined;
|
||||
}
|
||||
var index = 0;
|
||||
var checkOne = () => {
|
||||
if (matchSeq(seq)) {
|
||||
var checkSpec = checkList[index++];
|
||||
if (checkSpec.project.getSourceFileFromName(checkSpec.fileName)) {
|
||||
this.syntacticCheck(checkSpec.fileName, checkSpec.project);
|
||||
this.immediateId = setImmediate(() => {
|
||||
this.semanticCheck(checkSpec.fileName, checkSpec.project);
|
||||
this.immediateId = undefined;
|
||||
if (checkList.length > index) {
|
||||
this.errorTimer = setTimeout(checkOne, followMs);
|
||||
}
|
||||
else {
|
||||
this.errorTimer = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((checkList.length > index) && (matchSeq(seq))) {
|
||||
this.errorTimer = setTimeout(checkOne, ms);
|
||||
}
|
||||
}
|
||||
|
||||
getDefinition(line: number, col: number, fileName: string): protocol.FileSpan[] {
|
||||
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);
|
||||
|
||||
var definitions = compilerService.languageService.getDefinitionAtPosition(file, position);
|
||||
if (!definitions) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return definitions.map(def => ({
|
||||
file: def.fileName,
|
||||
start: compilerService.host.positionToLineCol(def.fileName, def.textSpan.start),
|
||||
end: compilerService.host.positionToLineCol(def.fileName, ts.textSpanEnd(def.textSpan))
|
||||
}));
|
||||
}
|
||||
|
||||
getRenameLocations(line: number, col: number, fileName: string,findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
|
||||
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);
|
||||
var renameInfo = compilerService.languageService.getRenameInfo(file, position);
|
||||
if (!renameInfo) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
if (!renameInfo.canRename) {
|
||||
return {
|
||||
info: renameInfo,
|
||||
locs: []
|
||||
};
|
||||
}
|
||||
|
||||
var renameLocations = compilerService.languageService.findRenameLocations(file, position, findInStrings, findInComments);
|
||||
if (!renameLocations) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
var bakedRenameLocs = renameLocations.map(location => (<protocol.FileSpan>{
|
||||
file: location.fileName,
|
||||
start: compilerService.host.positionToLineCol(location.fileName, location.textSpan.start),
|
||||
end: compilerService.host.positionToLineCol(location.fileName, ts.textSpanEnd(location.textSpan)),
|
||||
})).sort((a, b) => {
|
||||
if (a.file < b.file) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.file > b.file) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
// reverse sort assuming no overlap
|
||||
if (a.start.line < b.start.line) {
|
||||
return 1;
|
||||
}
|
||||
else if (a.start.line > b.start.line) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return b.start.col - a.start.col;
|
||||
}
|
||||
}
|
||||
}).reduce<protocol.SpanGroup[]>((accum: protocol.SpanGroup[], cur: protocol.FileSpan) => {
|
||||
var curFileAccum: protocol.SpanGroup;
|
||||
if (accum.length > 0) {
|
||||
curFileAccum = accum[accum.length - 1];
|
||||
if (curFileAccum.file != cur.file) {
|
||||
curFileAccum = undefined;
|
||||
}
|
||||
}
|
||||
if (!curFileAccum) {
|
||||
curFileAccum = { file: cur.file, locs: [] };
|
||||
accum.push(curFileAccum);
|
||||
}
|
||||
curFileAccum.locs.push({ start: cur.start, end: cur.end });
|
||||
return accum;
|
||||
}, []);
|
||||
|
||||
return { info: renameInfo, locs: bakedRenameLocs };
|
||||
}
|
||||
|
||||
getReferences(line: number, col: number, fileName: string): protocol.ReferencesResponseBody {
|
||||
// TODO: get all projects for this file; report refs for all projects deleting duplicates
|
||||
// can avoid duplicates by eliminating same ref file from subsequent projects
|
||||
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);
|
||||
|
||||
var references = compilerService.languageService.getReferencesAtPosition(file, position);
|
||||
if (!references) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
var nameInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
|
||||
if (!nameInfo) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
var displayString = ts.displayPartsToString(nameInfo.displayParts);
|
||||
var nameSpan = nameInfo.textSpan;
|
||||
var nameColStart = compilerService.host.positionToLineCol(file, nameSpan.start).col;
|
||||
var nameText = compilerService.host.getScriptSnapshot(file).getText(nameSpan.start, ts.textSpanEnd(nameSpan));
|
||||
var bakedRefs: protocol.ReferencesResponseItem[] = references.map((ref) => {
|
||||
var start = compilerService.host.positionToLineCol(ref.fileName, ref.textSpan.start);
|
||||
var refLineSpan = compilerService.host.lineToTextSpan(ref.fileName, start.line - 1);
|
||||
var snap = compilerService.host.getScriptSnapshot(ref.fileName);
|
||||
var lineText = snap.getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
|
||||
return {
|
||||
file: ref.fileName,
|
||||
start: start,
|
||||
lineText: lineText,
|
||||
end: compilerService.host.positionToLineCol(ref.fileName, ts.textSpanEnd(ref.textSpan)),
|
||||
isWriteAccess: ref.isWriteAccess
|
||||
};
|
||||
}).sort(compareFileStart);
|
||||
return {
|
||||
refs: bakedRefs,
|
||||
symbolName: nameText,
|
||||
symbolStartCol: nameColStart,
|
||||
symbolDisplayString: displayString
|
||||
};
|
||||
}
|
||||
|
||||
openClientFile(fileName: string) {
|
||||
var file = ts.normalizePath(fileName);
|
||||
this.projectService.openClientFile(file);
|
||||
}
|
||||
|
||||
getQuickInfo(line: number, col: number, fileName: string): protocol.QuickInfoResponseBody {
|
||||
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);
|
||||
var quickInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
|
||||
if (!quickInfo) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
var displayString = ts.displayPartsToString(quickInfo.displayParts);
|
||||
var docString = ts.displayPartsToString(quickInfo.documentation);
|
||||
return {
|
||||
kind: quickInfo.kind,
|
||||
kindModifiers: quickInfo.kindModifiers,
|
||||
start: compilerService.host.positionToLineCol(file, quickInfo.textSpan.start),
|
||||
end: compilerService.host.positionToLineCol(file, ts.textSpanEnd(quickInfo.textSpan)),
|
||||
displayString: displayString,
|
||||
documentation: docString,
|
||||
};
|
||||
}
|
||||
|
||||
getFormattingEditsForRange(line: number, col: number, endLine: number, endCol: number, fileName: string): protocol.CodeEdit[] {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
var compilerService = project.compilerService;
|
||||
var startPosition = compilerService.host.lineColToPosition(file, line, col);
|
||||
var endPosition = compilerService.host.lineColToPosition(file, endLine, endCol);
|
||||
|
||||
// TODO: avoid duplicate code (with formatonkey)
|
||||
var edits = compilerService.languageService.getFormattingEditsForRange(file, startPosition, endPosition, compilerService.formatCodeOptions);
|
||||
if (!edits) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return edits.map((edit) => {
|
||||
return {
|
||||
start: compilerService.host.positionToLineCol(file, edit.span.start),
|
||||
end: compilerService.host.positionToLineCol(file, ts.textSpanEnd(edit.span)),
|
||||
newText: edit.newText ? edit.newText : ""
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getFormattingEditsAfterKeystroke(line: number, col: number, key: string, fileName: string): protocol.CodeEdit[] {
|
||||
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);
|
||||
var edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
|
||||
compilerService.formatCodeOptions);
|
||||
if ((key == "\n") && ((!edits) || (edits.length == 0) || allEditsBeforePos(edits, position))) {
|
||||
// TODO: get these options from host
|
||||
var editorOptions: ts.EditorOptions = {
|
||||
IndentSize: 4,
|
||||
TabSize: 4,
|
||||
NewLineCharacter: "\n",
|
||||
ConvertTabsToSpaces: true,
|
||||
};
|
||||
var indentPosition = compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);
|
||||
var spaces = generateSpaces(indentPosition);
|
||||
if (indentPosition > 0) {
|
||||
edits.push({ span: ts.createTextSpanFromBounds(position, position), newText: spaces });
|
||||
}
|
||||
}
|
||||
|
||||
if (!edits) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return edits.map((edit) => {
|
||||
return {
|
||||
start: compilerService.host.positionToLineCol(file,
|
||||
edit.span.start),
|
||||
end: compilerService.host.positionToLineCol(file,
|
||||
ts.textSpanEnd(edit.span)),
|
||||
newText: edit.newText ? edit.newText : ""
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getCompletions(line: number, col: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
|
||||
if (!prefix) {
|
||||
prefix = "";
|
||||
}
|
||||
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);
|
||||
|
||||
var completions = compilerService.languageService.getCompletionsAtPosition(file, position);
|
||||
if (!completions) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
|
||||
if (completions.isMemberCompletion || entry.name.indexOf(prefix) == 0) {
|
||||
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);
|
||||
var project = this.projectService.getProjectForFile(fileName);
|
||||
if (project) {
|
||||
accum.push({ fileName, project });
|
||||
}
|
||||
return accum;
|
||||
}, []);
|
||||
|
||||
if (checkList.length > 0) {
|
||||
this.updateErrorCheck(checkList, this.changeSeq,(n) => n == this.changeSeq, delay)
|
||||
}
|
||||
}
|
||||
|
||||
change(line: number, col: number, endLine: number, endCol: number, insertString: string, fileName: string) {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
var compilerService = project.compilerService;
|
||||
var start = compilerService.host.lineColToPosition(file, line, col);
|
||||
var end = compilerService.host.lineColToPosition(file, endLine, endCol);
|
||||
if (start >= 0) {
|
||||
compilerService.host.editScript(file, start, end, insertString);
|
||||
this.changeSeq++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reload(fileName: string, tempFileName: string, reqSeq = 0) {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var tmpfile = ts.normalizePath(tempFileName);
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
this.changeSeq++;
|
||||
// make sure no changes happen before this one is finished
|
||||
project.compilerService.host.reloadScript(file, tmpfile,() => {
|
||||
this.output(undefined, CommandNames.Reload, reqSeq);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
saveToTmp(fileName: string, tempFileName: string) {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var tmpfile = ts.normalizePath(tempFileName);
|
||||
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
project.compilerService.host.saveTo(file, tmpfile);
|
||||
}
|
||||
}
|
||||
|
||||
closeClientFile(fileName: string) {
|
||||
var file = ts.normalizePath(fileName);
|
||||
this.projectService.closeClientFile(file);
|
||||
}
|
||||
|
||||
decorateNavigationBarItem(project: Project, fileName: string, items: ts.NavigationBarItem[]): protocol.NavigationBarItem[] {
|
||||
if (!items) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var compilerService = project.compilerService;
|
||||
|
||||
return items.map(item => ({
|
||||
text: item.text,
|
||||
kind: item.kind,
|
||||
kindModifiers: item.kindModifiers,
|
||||
spans: item.spans.map(span => ({
|
||||
start: compilerService.host.positionToLineCol(fileName, span.start),
|
||||
end: compilerService.host.positionToLineCol(fileName, ts.textSpanEnd(span))
|
||||
})),
|
||||
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems)
|
||||
}));
|
||||
}
|
||||
|
||||
getNavigationBarItems(fileName: string): protocol.NavigationBarItem[] {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
var compilerService = project.compilerService;
|
||||
var items = compilerService.languageService.getNavigationBarItems(file);
|
||||
if (!items) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return this.decorateNavigationBarItem(project, fileName, items);
|
||||
}
|
||||
|
||||
getNavigateToItems(searchTerm: string, fileName: string): protocol.NavtoItem[] {
|
||||
var file = ts.normalizePath(fileName);
|
||||
var project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
var compilerService = project.compilerService;
|
||||
var navItems = sortNavItems(compilerService.languageService.getNavigateToItems(searchTerm));
|
||||
if (!navItems) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return navItems.map((navItem) => {
|
||||
var start = compilerService.host.positionToLineCol(navItem.fileName, navItem.textSpan.start);
|
||||
var end = compilerService.host.positionToLineCol(navItem.fileName, ts.textSpanEnd(navItem.textSpan));
|
||||
var bakedItem: protocol.NavtoItem = {
|
||||
name: navItem.name,
|
||||
kind: navItem.kind,
|
||||
file: navItem.fileName,
|
||||
start: start,
|
||||
end: end,
|
||||
};
|
||||
if (navItem.kindModifiers && (navItem.kindModifiers != "")) {
|
||||
bakedItem.kindModifiers = navItem.kindModifiers;
|
||||
}
|
||||
if (navItem.matchKind != 'none') {
|
||||
bakedItem.matchKind = navItem.matchKind;
|
||||
}
|
||||
if (navItem.containerName && (navItem.containerName.length > 0)) {
|
||||
bakedItem.containerName = navItem.containerName;
|
||||
}
|
||||
if (navItem.containerKind && (navItem.containerKind.length > 0)) {
|
||||
bakedItem.containerKind = navItem.containerKind;
|
||||
}
|
||||
return bakedItem;
|
||||
});
|
||||
}
|
||||
|
||||
getBraceMatching(line: number, col: number, fileName: string): protocol.TextSpan[] {
|
||||
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);
|
||||
|
||||
var spans = compilerService.languageService.getBraceMatchingAtPosition(file, position);
|
||||
if (!spans) {
|
||||
throw Errors.NoContent;
|
||||
}
|
||||
|
||||
return spans.map(span => ({
|
||||
start: compilerService.host.positionToLineCol(file, span.start),
|
||||
end: compilerService.host.positionToLineCol(file, span.start + span.length)
|
||||
}));
|
||||
}
|
||||
|
||||
onMessage(message: string) {
|
||||
try {
|
||||
var request = <protocol.Request>JSON.parse(message);
|
||||
var response: any;
|
||||
switch (request.command) {
|
||||
case CommandNames.Definition: {
|
||||
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
response = this.getDefinition(defArgs.line, defArgs.col, defArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.References: {
|
||||
var refArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
response = this.getReferences(refArgs.line, refArgs.col, refArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Rename: {
|
||||
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
|
||||
response = this.getRenameLocations(renameArgs.line, renameArgs.col, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Open: {
|
||||
var openArgs = <protocol.FileRequestArgs>request.arguments;
|
||||
this.openClientFile(openArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Quickinfo: {
|
||||
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.col, quickinfoArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Format: {
|
||||
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
|
||||
response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.col, formatArgs.endLine, formatArgs.endCol, formatArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Formatonkey: {
|
||||
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
|
||||
response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.col, formatOnKeyArgs.key, formatOnKeyArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Completions: {
|
||||
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
|
||||
response = this.getCompletions(request.arguments.line, request.arguments.col, completionsArgs.prefix, request.arguments.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.CompletionDetails: {
|
||||
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
|
||||
response = this.getCompletionEntryDetails(request.arguments.line, request.arguments.col, completionDetailsArgs.entryNames,
|
||||
request.arguments.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Geterr: {
|
||||
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
|
||||
response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Change: {
|
||||
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
|
||||
this.change(changeArgs.line, changeArgs.col, changeArgs.endLine, changeArgs.endCol,
|
||||
changeArgs.insertString, changeArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Reload: {
|
||||
var reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
|
||||
this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Saveto: {
|
||||
var savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
|
||||
this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Close: {
|
||||
var closeArgs = <protocol.FileRequestArgs>request.arguments;
|
||||
this.closeClientFile(closeArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Navto: {
|
||||
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
|
||||
response = this.getNavigateToItems(navtoArgs.searchTerm, navtoArgs.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.Brace: {
|
||||
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
response = this.getBraceMatching(braceArguments.line, braceArguments.col, braceArguments.file);
|
||||
break;
|
||||
}
|
||||
case CommandNames.NavBar: {
|
||||
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
|
||||
response = this.getNavigationBarItems(navBarArgs.file);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.projectService.log("Unrecognized JSON command: " + message);
|
||||
this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (response) {
|
||||
this.output(response, request.command, request.seq);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
if (err instanceof OperationCanceledException) {
|
||||
// Handle cancellation exceptions
|
||||
}
|
||||
this.logError(err, message);
|
||||
this.output(undefined, request ? request.command : CommandNames.Unknown, request ? request.seq : 0, "Error processing request. " + err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -991,6 +991,7 @@ module ts {
|
|||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
[s: string]: boolean | number| string;
|
||||
}
|
||||
|
||||
export interface DefinitionInfo {
|
||||
|
|
|
@ -1616,6 +1616,7 @@ declare module "typescript" {
|
|||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
[s: string]: boolean | number | string;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
|
|
|
@ -5228,6 +5228,9 @@ declare module "typescript" {
|
|||
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
>PlaceOpenBraceOnNewLineForControlBlocks : boolean
|
||||
|
||||
[s: string]: boolean | number | string;
|
||||
>s : string
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
>DefinitionInfo : DefinitionInfo
|
||||
|
|
|
@ -1647,6 +1647,7 @@ declare module "typescript" {
|
|||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
[s: string]: boolean | number | string;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
|
|
|
@ -5372,6 +5372,9 @@ declare module "typescript" {
|
|||
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
>PlaceOpenBraceOnNewLineForControlBlocks : boolean
|
||||
|
||||
[s: string]: boolean | number | string;
|
||||
>s : string
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
>DefinitionInfo : DefinitionInfo
|
||||
|
|
|
@ -1648,6 +1648,7 @@ declare module "typescript" {
|
|||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
[s: string]: boolean | number | string;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
|
|
|
@ -5324,6 +5324,9 @@ declare module "typescript" {
|
|||
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
>PlaceOpenBraceOnNewLineForControlBlocks : boolean
|
||||
|
||||
[s: string]: boolean | number | string;
|
||||
>s : string
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
>DefinitionInfo : DefinitionInfo
|
||||
|
|
|
@ -1685,6 +1685,7 @@ declare module "typescript" {
|
|||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
|
||||
PlaceOpenBraceOnNewLineForFunctions: boolean;
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
[s: string]: boolean | number | string;
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
fileName: string;
|
||||
|
|
|
@ -5497,6 +5497,9 @@ declare module "typescript" {
|
|||
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
|
||||
>PlaceOpenBraceOnNewLineForControlBlocks : boolean
|
||||
|
||||
[s: string]: boolean | number | string;
|
||||
>s : string
|
||||
}
|
||||
interface DefinitionInfo {
|
||||
>DefinitionInfo : DefinitionInfo
|
||||
|
|
12
tests/cases/fourslash/definition.ts
Normal file
12
tests/cases/fourslash/definition.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: b.ts
|
||||
////import n = require('a/*1*/');
|
||||
////var x = new n.Foo();
|
||||
|
||||
// @Filename: a.ts
|
||||
//// /*2*/export class Foo {}
|
||||
|
||||
goTo.marker('1');
|
||||
goTo.definition();
|
||||
verify.caretAtMarker('2');
|
43
tests/cases/fourslash/server/brace.ts
Normal file
43
tests/cases/fourslash/server/brace.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
//////curly braces
|
||||
////module Foo [|{
|
||||
//// class Bar [|{
|
||||
//// private f() [|{
|
||||
//// }|]
|
||||
////
|
||||
//// private f2() [|{
|
||||
//// if (true) [|{ }|] [|{ }|];
|
||||
//// }|]
|
||||
//// }|]
|
||||
////}|]
|
||||
////
|
||||
//////parenthesis
|
||||
////class FooBar {
|
||||
//// private f[|()|] {
|
||||
//// return [|([|(1 + 1)|])|];
|
||||
//// }
|
||||
////
|
||||
//// private f2[|()|] {
|
||||
//// if [|(true)|] { }
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
//////square brackets
|
||||
////class Baz {
|
||||
//// private f() {
|
||||
//// var a: any[|[]|] = [|[[|[1, 2]|], [|[3, 4]|], 5]|];
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////// angular brackets
|
||||
////class TemplateTest [|<T1, T2 extends Array>|] {
|
||||
//// public foo(a, b) {
|
||||
//// return [|<any>|] a;
|
||||
//// }
|
||||
////}
|
||||
|
||||
test.ranges().forEach((range) => {
|
||||
verify.matchingBracePositionInCurrentFile(range.start, range.end - 1);
|
||||
verify.matchingBracePositionInCurrentFile(range.end - 1, range.start);
|
||||
});
|
17
tests/cases/fourslash/server/completions.ts
Normal file
17
tests/cases/fourslash/server/completions.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////var x: string[] = [];
|
||||
////x.forEach(function (y) { y/*1*/
|
||||
////x.forEach(y => y/*2*/
|
||||
|
||||
goTo.marker('1');
|
||||
edit.insert('.');
|
||||
verify.memberListContains('trim');
|
||||
verify.memberListCount(20);
|
||||
edit.insert('});'); // need the following lines to not have parse errors in order for completion list to appear
|
||||
|
||||
goTo.marker('2');
|
||||
edit.insert('.');
|
||||
verify.memberListContains('trim');
|
||||
verify.memberListCount(20);
|
||||
|
18
tests/cases/fourslash/server/completions2.ts
Normal file
18
tests/cases/fourslash/server/completions2.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////class Foo {
|
||||
////}
|
||||
////module Foo {
|
||||
//// export var x: number;
|
||||
////}
|
||||
////Foo./**/
|
||||
|
||||
goTo.marker("");
|
||||
verify.completionListContains("x");
|
||||
|
||||
// Make an edit
|
||||
edit.insert("a");
|
||||
edit.backspace();
|
||||
|
||||
// Checking for completion details after edit should work too
|
||||
verify.completionEntryDetailIs("x", "(var) Foo.x: number");
|
12
tests/cases/fourslash/server/definition.ts
Normal file
12
tests/cases/fourslash/server/definition.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: b.ts
|
||||
////import n = require('a/*1*/');
|
||||
////var x = new n.Foo();
|
||||
|
||||
// @Filename: a.ts
|
||||
//// /*2*/export class Foo {}
|
||||
|
||||
goTo.marker('1');
|
||||
goTo.definition();
|
||||
verify.caretAtMarker('2');
|
8
tests/cases/fourslash/server/format.ts
Normal file
8
tests/cases/fourslash/server/format.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
/////**/module Default{var x= ( { } ) ;}
|
||||
|
||||
|
||||
format.document();
|
||||
goTo.marker();
|
||||
verify.currentLineContentIs('module Default { var x = ({}); }');
|
12
tests/cases/fourslash/server/formatonkey.ts
Normal file
12
tests/cases/fourslash/server/formatonkey.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////switch (1) {
|
||||
//// case 1:
|
||||
//// {
|
||||
//// /*1*/
|
||||
//// break;
|
||||
////}
|
||||
|
||||
goTo.marker("1");
|
||||
edit.insert("}");
|
||||
verify.currentLineContentIs(" }");
|
52
tests/cases/fourslash/server/navbar.ts
Normal file
52
tests/cases/fourslash/server/navbar.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////// Interface
|
||||
////{| "itemName": "IPoint", "kind": "interface", "parentName": "" |}interface IPoint {
|
||||
//// {| "itemName": "getDist", "kind": "method", "parentName": "IPoint" |}getDist(): number;
|
||||
//// {| "itemName": "new()", "kind": "construct", "parentName": "IPoint" |}new(): IPoint;
|
||||
//// {| "itemName": "()", "kind": "call", "parentName": "IPoint" |}(): any;
|
||||
//// {| "itemName": "[]", "kind": "index", "parentName": "IPoint" |}[x:string]: number;
|
||||
//// {| "itemName": "prop", "kind": "property", "parentName": "IPoint" |}prop: string;
|
||||
////}
|
||||
////
|
||||
/////// Module
|
||||
////{| "itemName": "Shapes", "kind": "module", "parentName": "" |}module Shapes {
|
||||
////
|
||||
//// // Class
|
||||
//// {| "itemName": "Point", "kind": "class", "parentName": "Shapes" |}export class Point implements IPoint {
|
||||
//// {| "itemName": "constructor", "kind": "constructor", "parentName": "Shapes.Point" |}constructor (public x: number, public y: number) { }
|
||||
////
|
||||
//// // Instance member
|
||||
//// {| "itemName": "getDist", "kind": "method", "parentName": "Shapes.Point" |}getDist() { return Math.sqrt(this.x * this.x + this.y * this.y); }
|
||||
////
|
||||
//// // Getter
|
||||
//// {| "itemName": "value", "kind": "getter", "parentName": "Shapes.Point" |}get value(): number { return 0; }
|
||||
////
|
||||
//// // Setter
|
||||
//// {| "itemName": "value", "kind": "setter", "parentName": "Shapes.Point" |}set value(newValue: number) { return; }
|
||||
////
|
||||
//// // Static member
|
||||
//// {| "itemName": "origin", "kind": "property", "parentName": "Shapes.Point" |}static origin = new Point(0, 0);
|
||||
////
|
||||
//// // Static method
|
||||
//// {| "itemName": "getOrigin", "kind": "method", "parentName": "Shapes.Point" |}private static getOrigin() { return Point.origin;}
|
||||
//// }
|
||||
////
|
||||
//// {| "itemName": "Values", "kind": "enum", "parentName": "Shapes" |}enum Values {
|
||||
//// value1,
|
||||
//// {| "itemName": "value2", "kind": "property", "parentName": "Shapes.Values" |}value2,
|
||||
//// value3,
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////// Local variables
|
||||
////{| "itemName": "p", "kind": "var", "parentName": "" |}var p: IPoint = new Shapes.Point(3, 4);
|
||||
////{| "itemName": "dist", "kind": "var", "parentName": "" |}var dist = p.getDist();
|
||||
|
||||
test.markers().forEach((marker) => {
|
||||
if (marker.data) {
|
||||
verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName);
|
||||
}
|
||||
});
|
||||
|
||||
verify.getScriptLexicalStructureListCount(23);
|
28
tests/cases/fourslash/server/navto.ts
Normal file
28
tests/cases/fourslash/server/navto.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
/////// Module
|
||||
////{| "itemName": "Shapes", "kind": "module", "parentName": "", "matchKind": "substring" |}module Shapes {
|
||||
////
|
||||
//// // Class
|
||||
//// {| "itemName": "Point", "kind": "class", "parentName": "Shapes", "matchKind": "substring" |}export class Point {
|
||||
//// // Instance member
|
||||
//// {| "itemName": "originPointAttheHorizon", "kind": "property", "parentName": "Point", "matchKind": "substring"|}private originPointAttheHorizon = 0.0;
|
||||
////
|
||||
//// // Getter
|
||||
//// {| "itemName": "distanceFromOrigin", "kind": "getter", "parentName": "Point", "matchKind": "substring" |}get distanceFromOrigin(): number { return 0; }
|
||||
////
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////// Local variables
|
||||
////{| "itemName": "myPointThatIJustInitiated", "kind": "var", "parentName": "", "matchKind": "substring"|}var myPointThatIJustInitiated = new Shapes.Point();
|
||||
|
||||
//// Testing for substring matching of navigationItems
|
||||
//var searchValue = "FromOrigin horizon INITIATED Shape Point";
|
||||
|
||||
test.markers().forEach((marker) => {
|
||||
if (marker.data) {
|
||||
var name = marker.data.itemName;
|
||||
verify.navigationItemsListContains(name, marker.data.kind, name.substr(1), marker.data.matchKind, marker.fileName, marker.data.parentName);
|
||||
}
|
||||
});
|
27
tests/cases/fourslash/server/quickinfo.ts
Normal file
27
tests/cases/fourslash/server/quickinfo.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////interface One {
|
||||
//// commonProperty: number;
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// commonProperty: string
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////var /*1*/x : One | Two;
|
||||
////
|
||||
////x./*2*/commonProperty;
|
||||
////x./*3*/commonFunction;
|
||||
|
||||
|
||||
goTo.marker("1");
|
||||
verify.quickInfoIs('(var) x: One | Two');
|
||||
|
||||
|
||||
goTo.marker("2");
|
||||
verify.quickInfoIs('(property) commonProperty: string | number');
|
||||
|
||||
goTo.marker("3");
|
||||
verify.quickInfoIs('(method) commonFunction(): number');
|
18
tests/cases/fourslash/server/references.ts
Normal file
18
tests/cases/fourslash/server/references.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// Global class reference.
|
||||
|
||||
// @Filename: referencesForGlobals_1.ts
|
||||
////class /*2*/globalClass {
|
||||
//// public f() { }
|
||||
////}
|
||||
|
||||
// @Filename: referencesForGlobals_2.ts
|
||||
///////<reference path="referencesForGlobals_1.ts" />
|
||||
////var c = /*1*/globalClass();
|
||||
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(2);
|
||||
|
||||
goTo.marker("2");
|
||||
verify.referencesCountIs(2);
|
11
tests/cases/fourslash/server/rename.ts
Normal file
11
tests/cases/fourslash/server/rename.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
///////<reference path="./Bar.ts" />
|
||||
|
||||
////function /**/[|Bar|]() {
|
||||
//// // This is a reference to [|Bar|] in a comment.
|
||||
//// "this is a reference to [|Bar|] in a string"
|
||||
////}
|
||||
|
||||
goTo.marker();
|
||||
verify.renameLocations(/*findInStrings:*/ true, /*findInComments:*/ true);
|
Loading…
Reference in a new issue