greybel-languageserver-core
Version:
Core functionality of language server for GreyScript
95 lines • 4.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentWorkspaceMerger = exports.DocumentWorkspaceMergerJob = void 0;
const fast_toposort_1 = require("fast-toposort");
const type_manager_1 = require("../type-manager");
const document_workspace_builder_1 = require("../document-manager/document-workspace-builder");
class DocumentWorkspaceMergerJob {
constructor(cache) {
this.cache = cache;
}
getTypeDocument(documentUri, context) {
const activeDocument = context.getRef(documentUri);
// collect imports with namespace if possible
if (activeDocument != null) {
const namespacesOfImports = (0, type_manager_1.aggregateImportsWithNamespaceFromLocations)(context.getDependencies(documentUri), context.getRefMap());
if (namespacesOfImports.length === 0) {
return activeDocument.typeDocument;
}
const mergedTypeDoc = activeDocument.typeDocument.merge(...namespacesOfImports.map((it) => {
return { document: it.typeDoc, namespaces: [{ exportFrom: 'module.exports', namespace: it.namespace }] };
}));
return mergedTypeDoc;
}
return activeDocument.typeDocument;
}
getExternalTypeDocumentsRelatedToDocument(document, context) {
const documentUri = document.textDocument.uri;
const documentUris = context.documents.map((item) => item.textDocument.uri);
// sort by it's usage
const documentGraph = context.documents.map((item) => {
const depUris = context.getDependencies(item.textDocument.uri);
return depUris.map((dep) => {
return [item.textDocument.uri, dep.location];
});
});
const topoSorted = (0, fast_toposort_1.toposort)(documentUris, documentGraph.flat());
const externalTypeDocs = new Array(topoSorted.length);
for (let index = topoSorted.length - 1; index >= 0; index--) {
const itemUri = topoSorted[index];
if (itemUri === documentUri)
continue;
const itemTypeDoc = this.getTypeDocument(itemUri, context);
if (itemTypeDoc == null)
continue;
externalTypeDocs[index] = itemTypeDoc;
}
const availableExternalTypeDocs = externalTypeDocs.filter((item) => item != null);
return availableExternalTypeDocs;
}
async process(document, context) {
const documentUri = document.textDocument.uri;
const cacheKey = this.cache.createCacheKey(document, context.documents);
if (this.cache.typeDocuments.has(cacheKey)) {
return this.cache.typeDocuments.get(cacheKey);
}
this.cache.registerCacheKey(cacheKey, documentUri);
await context.loadDependencies();
const externalTypeDocs = this.getExternalTypeDocumentsRelatedToDocument(document, context);
// collect imports with namespace
const namespacesOfImports = (0, type_manager_1.aggregateImportsWithNamespaceFromLocations)(context.getDependencies(documentUri), context.getRefMap());
const mergedTypeDoc = document.typeDocument.merge(...namespacesOfImports.map((it) => {
return { document: it.typeDoc, namespaces: [{ exportFrom: 'module.exports', namespace: it.namespace }] };
}), ...externalTypeDocs.map((it) => {
return { document: it };
}));
this.cache.typeDocuments.set(cacheKey, mergedTypeDoc);
return mergedTypeDoc;
}
}
exports.DocumentWorkspaceMergerJob = DocumentWorkspaceMergerJob;
class DocumentWorkspaceMerger {
constructor(cache) {
this.cache = cache;
this.pendingJobs = new Map();
}
async process(document, context) {
const workspaceBuilder = new document_workspace_builder_1.DocumentWorkspaceBuilder({ context });
const workspaceContext = await workspaceBuilder.build();
const job = new DocumentWorkspaceMergerJob(this.cache);
return job.process(document, workspaceContext);
}
async build(document, context) {
const existingJob = this.pendingJobs.get(document.textDocument.uri);
if (existingJob) {
return existingJob;
}
const job = this.process(document, context);
this.pendingJobs.set(document.textDocument.uri, job);
const result = await job;
this.pendingJobs.delete(document.textDocument.uri);
return result;
}
}
exports.DocumentWorkspaceMerger = DocumentWorkspaceMerger;
//# sourceMappingURL=document-workspace-merger.js.map