greybel-languageserver-core
Version:
Core functionality of language server for GreyScript
134 lines • 4.91 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentManager = void 0;
const events_1 = __importDefault(require("events"));
const greyscript_core_1 = require("greyscript-core");
const lru_cache_1 = require("lru-cache");
const non_blocking_schedule_1 = require("non-blocking-schedule");
const active_document_1 = require("./document-manager/active-document");
const document_scheduler_1 = require("./document-manager/document-scheduler");
const type_manager_1 = __importDefault(require("./type-manager"));
class DocumentManager extends events_1.default {
get context() {
return this._context;
}
setContext(context) {
this._context = context;
return this;
}
constructor(processingTimeout) {
super();
this._context = null;
this._pendingFiles = new Map();
this.documents = new lru_cache_1.LRUCache({
ttl: 1000 * 60 * 20,
ttlAutopurge: true
});
this._documentScheduler = new document_scheduler_1.DocumentScheduler(processingTimeout);
this.initEvents();
}
initEvents() {
this._documentScheduler.on('process', (document) => {
this.processAndPersist(document);
});
}
processAndPersist(document) {
const key = document.uri;
this._documentScheduler.cancel(document);
const result = this.process(document);
this.documents.set(key, result);
this.emit('processed', document, result);
return result;
}
process(textDocument) {
this._context.documentMerger.cache.flushCacheKey(textDocument.uri);
const content = textDocument.getText();
const parser = new greyscript_core_1.Parser(content, {
unsafe: true
});
const parsedPayload = parser.parseChunk();
const typeDocument = type_manager_1.default.analyze(textDocument.uri, parsedPayload);
return new active_document_1.ActiveDocument({
context: this._context,
version: textDocument.version,
textDocument,
typeDocument,
parsedPayload,
errors: [...parser.lexer.errors, ...parser.errors]
});
}
schedule(textDocument) {
if (this.documents.get(textDocument.uri)?.version === textDocument.version) {
return false;
}
return this._documentScheduler.schedule(textDocument);
}
async open(target) {
try {
const pendingFile = this._pendingFiles.get(target);
let textDocument;
if (pendingFile) {
textDocument = await pendingFile;
}
else {
const defer = this.context.fs.getTextDocument(target);
this._pendingFiles.set(target, defer);
textDocument = await defer;
}
if (textDocument == null) {
return null;
}
return (this.documents.get(textDocument.uri) ||
this.processAndPersist(textDocument));
}
catch (err) {
console.error(`Error opening document ${target}:`, err);
return null;
}
finally {
this._pendingFiles.delete(target);
}
}
async getOrOpen(target) {
const document = this.documents.get(target);
if (document) {
return document;
}
return this.open(target);
}
get(textDocument) {
return (this.documents.get(textDocument.uri) ||
this.processAndPersist(textDocument));
}
getLatest(document, timeout = 5000) {
return new Promise((resolve) => {
(0, non_blocking_schedule_1.schedule)(() => {
if (!this._documentScheduler.isScheduled(document)) {
return resolve(this.get(document));
}
const onTimeout = () => {
this.removeListener('processed', onProcessed);
resolve(this.get(document));
};
const onProcessed = (evDocument) => {
if (evDocument.uri === document.uri) {
this.removeListener('processed', onProcessed);
clearTimeout(timer);
resolve(this.get(document));
}
};
const timer = setTimeout(onTimeout, timeout);
this.addListener('processed', onProcessed);
});
});
}
clear(document) {
this.documents.delete(document.uri);
this.emit('cleared', document);
}
}
exports.DocumentManager = DocumentManager;
//# sourceMappingURL=document-manager.js.map