add cancellation support

This commit is contained in:
Vladimir Matveev
2016-06-14 17:30:55 -07:00
parent bd646d1142
commit adb726643a
5 changed files with 80 additions and 10 deletions

View File

@@ -110,6 +110,12 @@ var serverCoreSources = [
return path.join(serverDirectory, f);
});
var cancellationTokenSources = [
"cancellationToken.ts"
].map(function (f) {
return path.join(serverDirectory, f);
});
var serverSources = serverCoreSources.concat(servicesSources);
var languageServiceLibrarySources = [
@@ -517,8 +523,11 @@ compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].conca
});
var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js");
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: true });
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright, cancellationTokenFile].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");

View File

@@ -0,0 +1,34 @@
/// <reference path="node.d.ts"/>
// TODO: extract services types
interface HostCancellationToken {
isCancellationRequested(): boolean;
}
const fs: typeof NodeJS.fs = require("fs");
function createCancellationToken(args: string[]): HostCancellationToken {
let cancellationPipeName: string;
for (let i = 0; i < args.length - 1; i++) {
if (args[i] === "--cancellationPipeName") {
cancellationPipeName = args[i + 1];
break;
}
}
if (!cancellationPipeName) {
return { isCancellationRequested: () => false };
}
return {
isCancellationRequested() {
try {
fs.statSync(cancellationPipeName);
return true;
}
catch(e) {
return false;
}
}
};
}
export = createCancellationToken

View File

@@ -129,7 +129,7 @@ namespace ts.server {
private resolvedTypeReferenceDirectives: ts.FileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>;
private getCanonicalFileName: (fileName: string) => string;
constructor(private host: ServerHost, private project: Project) {
constructor(private host: ServerHost, private project: Project, private cancellationToken: HostCancellationToken) {
this.getCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
this.resolvedModuleNames = createFileMap<Map<ResolvedModuleWithFailedLookupLocations>>();
this.resolvedTypeReferenceDirectives = createFileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
@@ -188,6 +188,10 @@ namespace ts.server {
}
}
getCancellationToken() {
return this.cancellationToken;
}
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective);
}
@@ -316,7 +320,7 @@ namespace ts.server {
compilerOptions.allowNonTsExtensions = true;
}
this.lsHost = new LSHost(this.projectService.host, this);
this.lsHost = new LSHost(this.projectService.host, this, this.projectService.cancellationToken);
this.lsHost.setCompilationSettings(compilerOptions);
this.languageService = ts.createLanguageService(this.lsHost, documentRegistry);
}
@@ -642,7 +646,10 @@ namespace ts.server {
private documentRegistry: ts.DocumentRegistry;
constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) {
constructor(public host: ServerHost,
public psLogger: Logger,
public cancellationToken: HostCancellationToken,
public eventHandler?: ProjectServiceEventHandler) {
// ts.disableIncrementalParsing = true;
this.setDefaultHostConfiguration();
this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());

View File

@@ -92,8 +92,8 @@ namespace ts.server {
}
class IOSession extends Session {
constructor(host: ServerHost, logger: ts.server.Logger) {
super(host, Buffer.byteLength, process.hrtime, logger);
constructor(host: ServerHost, cancellationToken: HostCancellationToken, logger: ts.server.Logger) {
super(host, cancellationToken, Buffer.byteLength, process.hrtime, logger);
}
exit() {
@@ -294,7 +294,21 @@ namespace ts.server {
sys.setTimeout = setTimeout;
sys.clearTimeout = clearTimeout;
const ioSession = new IOSession(sys, logger);
let cancellationToken: HostCancellationToken;
try {
let cancellationPipeName: string;
if (cancellationPipeName) {
const factory = require("./cancellationToken");
cancellationToken = factory(sys.args);
}
}
catch(e) {
cancellationToken = {
isCancellationRequested: () => false
}
}
const ioSession = new IOSession(sys, cancellationToken, logger);
process.on("uncaughtException", function(err: Error) {
ioSession.logError(err, "unknown");
});

View File

@@ -156,12 +156,12 @@ namespace ts.server {
constructor(
private host: ServerHost,
private cancellationToken: HostCancellationToken,
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
private logger: Logger
) {
private logger: Logger) {
this.projectService =
new ProjectService(host, logger, (eventName, project, fileName) => {
new ProjectService(host, logger, cancellationToken, (eventName, project, fileName) => {
this.handleEvent(eventName, project, fileName);
});
}
@@ -1067,6 +1067,10 @@ namespace ts.server {
return { response, responseRequired: true };
}
private canceledResponse() {
return { canceled: true, responseRequired: true };
}
private handlers: Map<(request: protocol.Request) => { response?: any, responseRequired?: boolean }> = {
[CommandNames.OpenExternalProject]: (request: protocol.OpenExternalProjectRequest) => {
this.projectService.openExternalProject(request.arguments);
@@ -1282,6 +1286,8 @@ namespace ts.server {
catch (err) {
if (err instanceof OperationCanceledException) {
// Handle cancellation exceptions
this.output({ canceled: true }, request.command, request.seq);
return;
}
this.logError(err, message);
this.output(