mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 03:54:24 +01:00
[folding] hook up cancellation
This commit is contained in:
@@ -4,17 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { TextDocument, Position } from 'vscode-languageserver';
|
||||
import { TextDocument, Position, CancellationToken } from 'vscode-languageserver';
|
||||
import { createScanner, SyntaxKind, ScanError } from 'jsonc-parser';
|
||||
import { FoldingRangeType, FoldingRange, FoldingRangeList } from './protocol/foldingProvider.proposed';
|
||||
|
||||
export function getFoldingRegions(document: TextDocument) {
|
||||
export function getFoldingRegions(document: TextDocument, cancellationToken: CancellationToken | null) {
|
||||
let ranges: FoldingRange[] = [];
|
||||
let stack: FoldingRange[] = [];
|
||||
let prevStart = -1;
|
||||
let scanner = createScanner(document.getText(), false);
|
||||
let token = scanner.scan();
|
||||
while (token !== SyntaxKind.EOF) {
|
||||
if (cancellationToken && cancellationToken.isCancellationRequested) {
|
||||
return null;
|
||||
}
|
||||
switch (token) {
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
case SyntaxKind.OpenBracketToken: {
|
||||
@@ -18,7 +18,7 @@ import { startsWith } from './utils/strings';
|
||||
import { formatError, runSafe, runSafeAsync } from './utils/errors';
|
||||
import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration } from 'vscode-json-languageservice';
|
||||
import { getLanguageModelCache } from './languageModelCache';
|
||||
import { getFoldingRegions } from './folding';
|
||||
import { getFoldingRegions } from './jsonFolding';
|
||||
|
||||
import { FoldingRangesRequest, FoldingProviderServerCapabilities } from './protocol/foldingProvider.proposed';
|
||||
|
||||
@@ -260,17 +260,21 @@ function validateTextDocument(textDocument: TextDocument): void {
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let jsonDocument = getJSONDocument(textDocument);
|
||||
let jsonDocument = getJSONDocument(textDocument);
|
||||
let version = textDocument.version;
|
||||
|
||||
let documentSettings: DocumentLanguageSettings = textDocument.languageId === 'jsonc' ? { comments: 'ignore', trailingCommas: 'ignore' } : { comments: 'error', trailingCommas: 'error' };
|
||||
languageService.doValidation(textDocument, jsonDocument, documentSettings).then(diagnostics => {
|
||||
// Send the computed diagnostics to VSCode.
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||
});
|
||||
} catch (e) {
|
||||
connection.console.error(formatError(`Error while validating ${textDocument.uri}`, e));
|
||||
}
|
||||
let documentSettings: DocumentLanguageSettings = textDocument.languageId === 'jsonc' ? { comments: 'ignore', trailingCommas: 'ignore' } : { comments: 'error', trailingCommas: 'error' };
|
||||
languageService.doValidation(textDocument, jsonDocument, documentSettings).then(diagnostics => {
|
||||
setTimeout(() => {
|
||||
let currDocument = documents.get(textDocument.uri);
|
||||
if (currDocument && currDocument.version === version) {
|
||||
// Send the computed diagnostics to VSCode.
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||
}
|
||||
}, 100);
|
||||
}, error => {
|
||||
connection.console.error(formatError(`Error while validating ${textDocument.uri}`, error));
|
||||
});
|
||||
}
|
||||
|
||||
connection.onDidChangeWatchedFiles((change) => {
|
||||
@@ -282,7 +286,7 @@ connection.onDidChangeWatchedFiles((change) => {
|
||||
}
|
||||
});
|
||||
if (hasChanges) {
|
||||
documents.all().forEach(validateTextDocument);
|
||||
documents.all().forEach(triggerValidation);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -320,19 +324,19 @@ connection.onHover(textDocumentPositionParams => {
|
||||
}, null, `Error while computing hover for ${textDocumentPositionParams.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onDocumentSymbol(documentSymbolParams => {
|
||||
connection.onDocumentSymbol((documentSymbolParams, token) => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(documentSymbolParams.textDocument.uri);
|
||||
let jsonDocument = getJSONDocument(document);
|
||||
return languageService.findDocumentSymbols(document, jsonDocument);
|
||||
}, [], `Error while computing document symbols for ${documentSymbolParams.textDocument.uri}`);
|
||||
}, [], `Error while computing document symbols for ${documentSymbolParams.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onDocumentRangeFormatting(formatParams => {
|
||||
connection.onDocumentRangeFormatting((formatParams, token) => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(formatParams.textDocument.uri);
|
||||
return languageService.format(document, formatParams.range, formatParams.options);
|
||||
}, [], `Error while formatting range for ${formatParams.textDocument.uri}`);
|
||||
}, [], `Error while formatting range for ${formatParams.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onRequest(DocumentColorRequest.type, params => {
|
||||
@@ -346,7 +350,7 @@ connection.onRequest(DocumentColorRequest.type, params => {
|
||||
}, [], `Error while computing document colors for ${params.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onRequest(ColorPresentationRequest.type, params => {
|
||||
connection.onRequest(ColorPresentationRequest.type, (params, token) => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
@@ -354,17 +358,17 @@ connection.onRequest(ColorPresentationRequest.type, params => {
|
||||
return languageService.getColorPresentations(document, jsonDocument, params.color, params.range);
|
||||
}
|
||||
return [];
|
||||
}, [], `Error while computing color presentations for ${params.textDocument.uri}`);
|
||||
}, [], `Error while computing color presentations for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onRequest(FoldingRangesRequest.type, params => {
|
||||
connection.onRequest(FoldingRangesRequest.type, (params, token) => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
return getFoldingRegions(document);
|
||||
return getFoldingRegions(document, token);
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing folding ranges for ${params.textDocument.uri}`);
|
||||
}, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
// Listen on the connection
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { TextDocument } from 'vscode-languageserver';
|
||||
import { getFoldingRegions } from '../folding';
|
||||
import { getFoldingRegions } from '../jsonFolding';
|
||||
|
||||
interface ExpectedIndentRange {
|
||||
startLine: number;
|
||||
@@ -18,8 +18,7 @@ interface ExpectedIndentRange {
|
||||
|
||||
function assertRanges(lines: string[], expected: ExpectedIndentRange[]): void {
|
||||
let document = TextDocument.create('test://foo/bar.json', 'json', 1, lines.join('\n'));
|
||||
let actual = getFoldingRegions(document).ranges;
|
||||
|
||||
let actual = getFoldingRegions(document, null)!.ranges;
|
||||
|
||||
let actualRanges = [];
|
||||
for (let i = 0; i < actual.length; i++) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { CancellationToken, ResponseError, ErrorCodes } from 'vscode-languageserver';
|
||||
|
||||
export function formatError(message: string, err: any): string {
|
||||
if (err instanceof Error) {
|
||||
let error = <Error>err;
|
||||
@@ -23,11 +25,31 @@ export function runSafeAsync<T>(func: () => Thenable<T>, errorVal: T, errorMessa
|
||||
return errorVal;
|
||||
});
|
||||
}
|
||||
export function runSafe<T>(func: () => T, errorVal: T, errorMessage: string): T {
|
||||
try {
|
||||
return func();
|
||||
} catch (e) {
|
||||
console.error(formatError(errorMessage, e));
|
||||
return errorVal;
|
||||
}
|
||||
}
|
||||
export function runSafe<T, E>(func: () => T, errorVal: T, errorMessage: string, token: CancellationToken): Thenable<T | ResponseError<E>> {
|
||||
return new Promise<T | ResponseError<E>>((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
if (token.isCancellationRequested) {
|
||||
resolve(cancelValue());
|
||||
} else {
|
||||
try {
|
||||
let result = func();
|
||||
if (token.isCancellationRequested) {
|
||||
resolve(cancelValue());
|
||||
return;
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error(formatError(errorMessage, e));
|
||||
resolve(errorVal);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
function cancelValue<E>() {
|
||||
console.log('cancelled');
|
||||
return new ResponseError<E>(ErrorCodes.RequestCancelled, 'Request cancelled');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user