233 lines
11 KiB
JavaScript
233 lines
11 KiB
JavaScript
|
"use strict";
|
||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||
|
if (k2 === undefined) k2 = k;
|
||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||
|
}
|
||
|
Object.defineProperty(o, k2, desc);
|
||
|
}) : (function(o, m, k, k2) {
|
||
|
if (k2 === undefined) k2 = k;
|
||
|
o[k2] = m[k];
|
||
|
}));
|
||
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.defaultMapperFactory = exports.SourceMap = void 0;
|
||
|
exports.createLanguage = createLanguage;
|
||
|
exports.forEachEmbeddedCode = forEachEmbeddedCode;
|
||
|
var source_map_1 = require("@volar/source-map");
|
||
|
Object.defineProperty(exports, "SourceMap", { enumerable: true, get: function () { return source_map_1.SourceMap; } });
|
||
|
__exportStar(require("./lib/editorFeatures"), exports);
|
||
|
__exportStar(require("./lib/linkedCodeMap"), exports);
|
||
|
__exportStar(require("./lib/types"), exports);
|
||
|
__exportStar(require("./lib/utils"), exports);
|
||
|
const source_map_2 = require("@volar/source-map");
|
||
|
const linkedCodeMap_1 = require("./lib/linkedCodeMap");
|
||
|
const defaultMapperFactory = mappings => new source_map_2.SourceMap(mappings);
|
||
|
exports.defaultMapperFactory = defaultMapperFactory;
|
||
|
function createLanguage(plugins, scriptRegistry, sync) {
|
||
|
const virtualCodeToSourceScriptMap = new WeakMap();
|
||
|
const virtualCodeToSourceMap = new WeakMap();
|
||
|
const virtualCodeToLinkedCodeMap = new WeakMap();
|
||
|
const language = {
|
||
|
mapperFactory: exports.defaultMapperFactory,
|
||
|
plugins,
|
||
|
scripts: {
|
||
|
fromVirtualCode(virtualCode) {
|
||
|
return virtualCodeToSourceScriptMap.get(virtualCode);
|
||
|
},
|
||
|
get(id, includeFsFiles = true) {
|
||
|
sync(id, includeFsFiles);
|
||
|
const result = scriptRegistry.get(id);
|
||
|
// The sync function provider may not always call the set function due to caching, so it is necessary to explicitly check isAssociationDirty.
|
||
|
if (result?.isAssociationDirty) {
|
||
|
this.set(id, result.snapshot, result.languageId);
|
||
|
}
|
||
|
return scriptRegistry.get(id);
|
||
|
},
|
||
|
set(id, snapshot, languageId, _plugins = plugins) {
|
||
|
if (!languageId) {
|
||
|
for (const plugin of plugins) {
|
||
|
languageId = plugin.getLanguageId?.(id);
|
||
|
if (languageId) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!languageId) {
|
||
|
console.warn(`languageId not found for ${id}`);
|
||
|
return;
|
||
|
}
|
||
|
let associatedOnly = false;
|
||
|
for (const plugin of plugins) {
|
||
|
if (plugin.isAssociatedFileOnly?.(id, languageId)) {
|
||
|
associatedOnly = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (scriptRegistry.has(id)) {
|
||
|
const sourceScript = scriptRegistry.get(id);
|
||
|
if (sourceScript.languageId !== languageId || sourceScript.associatedOnly !== associatedOnly) {
|
||
|
this.delete(id);
|
||
|
return this.set(id, snapshot, languageId);
|
||
|
}
|
||
|
else if (associatedOnly) {
|
||
|
sourceScript.snapshot = snapshot;
|
||
|
}
|
||
|
else if (sourceScript.isAssociationDirty || sourceScript.snapshot !== snapshot) {
|
||
|
// snapshot updated
|
||
|
sourceScript.snapshot = snapshot;
|
||
|
const codegenCtx = prepareCreateVirtualCode(sourceScript);
|
||
|
if (sourceScript.generated) {
|
||
|
const { updateVirtualCode, createVirtualCode } = sourceScript.generated.languagePlugin;
|
||
|
const newVirtualCode = updateVirtualCode
|
||
|
? updateVirtualCode(id, sourceScript.generated.root, snapshot, codegenCtx)
|
||
|
: createVirtualCode?.(id, languageId, snapshot, codegenCtx);
|
||
|
if (newVirtualCode) {
|
||
|
sourceScript.generated.root = newVirtualCode;
|
||
|
sourceScript.generated.embeddedCodes.clear();
|
||
|
for (const code of forEachEmbeddedCode(sourceScript.generated.root)) {
|
||
|
virtualCodeToSourceScriptMap.set(code, sourceScript);
|
||
|
sourceScript.generated.embeddedCodes.set(code.id, code);
|
||
|
}
|
||
|
return sourceScript;
|
||
|
}
|
||
|
else {
|
||
|
this.delete(id);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
triggerTargetsDirty(sourceScript);
|
||
|
}
|
||
|
else {
|
||
|
// not changed
|
||
|
return sourceScript;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// created
|
||
|
const sourceScript = {
|
||
|
id: id,
|
||
|
languageId,
|
||
|
snapshot,
|
||
|
associatedIds: new Set(),
|
||
|
targetIds: new Set(),
|
||
|
associatedOnly
|
||
|
};
|
||
|
scriptRegistry.set(id, sourceScript);
|
||
|
if (associatedOnly) {
|
||
|
return sourceScript;
|
||
|
}
|
||
|
for (const languagePlugin of _plugins) {
|
||
|
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot, prepareCreateVirtualCode(sourceScript));
|
||
|
if (virtualCode) {
|
||
|
sourceScript.generated = {
|
||
|
root: virtualCode,
|
||
|
languagePlugin,
|
||
|
embeddedCodes: new Map(),
|
||
|
};
|
||
|
for (const code of forEachEmbeddedCode(virtualCode)) {
|
||
|
virtualCodeToSourceScriptMap.set(code, sourceScript);
|
||
|
sourceScript.generated.embeddedCodes.set(code.id, code);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return sourceScript;
|
||
|
}
|
||
|
},
|
||
|
delete(id) {
|
||
|
const sourceScript = scriptRegistry.get(id);
|
||
|
if (sourceScript) {
|
||
|
sourceScript.generated?.languagePlugin.disposeVirtualCode?.(id, sourceScript.generated.root);
|
||
|
scriptRegistry.delete(id);
|
||
|
triggerTargetsDirty(sourceScript);
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
maps: {
|
||
|
get(virtualCode, sourceScript) {
|
||
|
let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot);
|
||
|
if (!mapCache) {
|
||
|
virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = new WeakMap());
|
||
|
}
|
||
|
if (!mapCache.has(sourceScript.snapshot)) {
|
||
|
const mappings = virtualCode.associatedScriptMappings?.get(sourceScript.id) ?? virtualCode.mappings;
|
||
|
mapCache.set(sourceScript.snapshot, language.mapperFactory(mappings));
|
||
|
}
|
||
|
return mapCache.get(sourceScript.snapshot);
|
||
|
},
|
||
|
*forEach(virtualCode) {
|
||
|
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
|
||
|
yield [
|
||
|
sourceScript,
|
||
|
this.get(virtualCode, sourceScript),
|
||
|
];
|
||
|
if (virtualCode.associatedScriptMappings) {
|
||
|
for (const [relatedScriptId] of virtualCode.associatedScriptMappings) {
|
||
|
const relatedSourceScript = scriptRegistry.get(relatedScriptId);
|
||
|
if (relatedSourceScript) {
|
||
|
yield [
|
||
|
relatedSourceScript,
|
||
|
this.get(virtualCode, relatedSourceScript),
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
linkedCodeMaps: {
|
||
|
get(virtualCode) {
|
||
|
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
|
||
|
let mapCache = virtualCodeToLinkedCodeMap.get(virtualCode.snapshot);
|
||
|
if (mapCache?.[0] !== sourceScript.snapshot) {
|
||
|
virtualCodeToLinkedCodeMap.set(virtualCode.snapshot, mapCache = [
|
||
|
sourceScript.snapshot,
|
||
|
virtualCode.linkedCodeMappings
|
||
|
? new linkedCodeMap_1.LinkedCodeMap(virtualCode.linkedCodeMappings)
|
||
|
: undefined,
|
||
|
]);
|
||
|
}
|
||
|
return mapCache[1];
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
return language;
|
||
|
function triggerTargetsDirty(sourceScript) {
|
||
|
sourceScript.targetIds.forEach(id => {
|
||
|
const sourceScript = scriptRegistry.get(id);
|
||
|
if (sourceScript) {
|
||
|
sourceScript.isAssociationDirty = true;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
function prepareCreateVirtualCode(sourceScript) {
|
||
|
for (const id of sourceScript.associatedIds) {
|
||
|
scriptRegistry.get(id)?.targetIds.delete(sourceScript.id);
|
||
|
}
|
||
|
sourceScript.associatedIds.clear();
|
||
|
sourceScript.isAssociationDirty = false;
|
||
|
return {
|
||
|
getAssociatedScript(id) {
|
||
|
sync(id, true);
|
||
|
const relatedSourceScript = scriptRegistry.get(id);
|
||
|
if (relatedSourceScript) {
|
||
|
relatedSourceScript.targetIds.add(sourceScript.id);
|
||
|
sourceScript.associatedIds.add(relatedSourceScript.id);
|
||
|
}
|
||
|
return relatedSourceScript;
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
function* forEachEmbeddedCode(virtualCode) {
|
||
|
yield virtualCode;
|
||
|
if (virtualCode.embeddedCodes) {
|
||
|
for (const embeddedCode of virtualCode.embeddedCodes) {
|
||
|
yield* forEachEmbeddedCode(embeddedCode);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//# sourceMappingURL=index.js.map
|