[html] htmlDocument cache

This commit is contained in:
Martin Aeschlimann 2016-09-19 13:36:37 -04:00
parent 1e35d6c328
commit 7465d39c5c
2 changed files with 96 additions and 10 deletions

View file

@ -4,12 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {
createConnection, IConnection,
TextDocuments, TextDocument, InitializeParams, InitializeResult
} from 'vscode-languageserver';
import {createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult} from 'vscode-languageserver';
import {HTMLDocument, getLanguageService, CompletionConfiguration, HTMLFormatConfiguration} from 'vscode-html-languageservice';
import {getLanguageModelCache} from './languageModelCache';
import * as nls from 'vscode-nls';
nls.config(process.env['VSCODE_NLS_CONFIG']);
@ -27,6 +26,14 @@ let documents: TextDocuments = new TextDocuments();
// for open, change and close text document events
documents.listen(connection);
let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => getLanguageService().parseHTMLDocument(document));
documents.onDidClose(e => {
htmlDocuments.onDocumentRemoved(e.document);
});
connection.onShutdown(() => {
htmlDocuments.dispose();
});
let workspacePath: string;
// After the server has started the client sends an initilize request. The server receives
@ -67,20 +74,16 @@ connection.onDidChangeConfiguration((change) => {
languageSettings = settings.html;
});
function getHTMLDocument(document: TextDocument): HTMLDocument {
return languageService.parseHTMLDocument(document);
}
connection.onCompletion(textDocumentPosition => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let htmlDocument = getHTMLDocument(document);
let htmlDocument = htmlDocuments.get(document);
let options = languageSettings && languageSettings.suggest;
return languageService.doComplete(document, textDocumentPosition.position, htmlDocument, options);
});
connection.onDocumentHighlight(documentHighlightParams => {
let document = documents.get(documentHighlightParams.textDocument.uri);
let htmlDocument = getHTMLDocument(document);
let htmlDocument = htmlDocuments.get(document);
return languageService.findDocumentHighlights(document, documentHighlightParams.position, htmlDocument);
});

View file

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TextDocument} from 'vscode-languageserver';
export interface LanguageModelCache<T> {
get(document: TextDocument): T;
onDocumentRemoved(document: TextDocument): void;
dispose(): void;
}
export function getLanguageModelCache<T>(maxEntries: number, cleanupIntervalTimeInSec: number, parse: (document: TextDocument) => T) : LanguageModelCache<T> {
let languageModels: { [uri:string]: {version:number, languageId: string, cTime: number, languageModel: T}} = {};
let nModels = 0;
let cleanupInterval = void 0;
if (cleanupIntervalTimeInSec > 0) {
cleanupInterval = setInterval(() => {
let cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;
let uris = Object.keys(languageModels);
for (let uri of uris) {
let languageModelInfo = languageModels[uri];
if (languageModelInfo.cTime < cutoffTime) {
delete languageModels[uri];
nModels--;
}
}
}, cleanupIntervalTimeInSec * 1000);
}
return {
get(document: TextDocument) : T {
let version = document.version;
let languageId = document.languageId;
let languageModelInfo = languageModels[document.uri];
if (languageModelInfo && languageModelInfo.version === version && languageModelInfo.languageId === languageId) {
languageModelInfo.cTime = Date.now();
return languageModelInfo.languageModel;
}
let languageModel = parse(document);
languageModels[document.uri] = { languageModel, version, languageId, cTime: Date.now()};
if (!languageModelInfo) {
nModels++;
}
if (nModels === maxEntries) {
let oldestTime = Number.MAX_VALUE;
let oldestUri = null;
for (let uri in languageModels) {
let languageModelInfo = languageModels[uri];
if (languageModelInfo.cTime < oldestTime) {
oldestUri = uri;
oldestTime = languageModelInfo.cTime;
}
}
if (oldestUri) {
delete languageModels[oldestUri];
nModels--;
}
}
return languageModel;
},
onDocumentRemoved(document: TextDocument) {
let uri = document.uri;
if (languageModels[uri]) {
delete languageModels[uri];
nModels--;
}
},
dispose() {
if (typeof cleanupInterval !== 'undefined') {
clearInterval(cleanupInterval);
cleanupInterval = void 0;
languageModels = {};
nModels = 0;
}
}
};
}