@compas/code-gen
Version:
Generate various boring parts of your server
110 lines (96 loc) • 3.28 kB
JavaScript
import { typesHasDifferentTypeAfterValidators } from "./optionality.js";
import { typeTargetsDetermine, typeTargetsGetUsed } from "./targets.js";
/**
* Cache to check if for the provided type we already have generated a variant.
*
* For each type, we can save multiple generated type names based on the different input
* options.
*
* @type {WeakMap<import("../generated/common/types").ExperimentalTypeSystemDefinition,
* Record<string, string>>}
*/
const typeCache = new WeakMap();
/**
* Add a cache entry for the type and its options to resolve to the generated type name.
*
* @param {import("../generate").GenerateContext} generateContext
* @param {import("../generated/common/types").ExperimentalTypeSystemDefinition} type
* @param {import("./generator").GenerateTypeOptions} options
* @param {string} name
*/
export function typesCacheAdd(generateContext, type, options, name) {
const typeTargets = typeTargetsDetermine(generateContext, type);
const usedTargets = typeTargetsGetUsed(typeTargets, options.targets);
const hasOptionalityDifferences = typesHasDifferentTypeAfterValidators(
generateContext,
type,
);
let existingSubCache = typeCache.get(type);
if (!existingSubCache) {
existingSubCache = {};
typeCache.set(type, existingSubCache);
}
const cacheKey = typeCacheFormatKey({
validatorState: options.validatorState,
hasOptionalityDifferences,
targets: usedTargets,
});
existingSubCache[cacheKey] = name;
}
/**
* Get a cache entry for the type and its option to resolve the generated type name if it
* already exists.
*
* @param {import("../generate").GenerateContext} generateContext
* @param {import("../generated/common/types").ExperimentalTypeSystemDefinition} type
* @param {import("./generator").GenerateTypeOptions} options
* @returns {string|undefined} name
*/
export function typesCacheGet(generateContext, type, options) {
const typeTargets = typeTargetsDetermine(generateContext, type);
const usedTargets = typeTargetsGetUsed(typeTargets, options.targets);
const hasOptionalityDifferences = typesHasDifferentTypeAfterValidators(
generateContext,
type,
);
const subCache = typeCache.get(type);
if (!subCache) {
return undefined;
}
const cacheKey = typeCacheFormatKey({
validatorState: options.validatorState,
hasOptionalityDifferences,
targets: usedTargets,
});
return subCache[cacheKey];
}
/**
* Get the already used type names for the provided type.
*
* @param {import("../generated/common/types").ExperimentalTypeSystemDefinition} type
* @returns {string[]}
*/
export function typesCacheGetUsedNames(type) {
const subCache = typeCache.get(type);
return Object.values(subCache ?? {});
}
/**
* Stable format of a cache key based on the options.
*
* @param {{
* validatorState: "input"|"output",
* targets: string[],
* hasOptionalityDifferences: boolean,
* }} options
* @returns {string}
*/
function typeCacheFormatKey(options) {
if (!options.hasOptionalityDifferences) {
return `optionality-diff=${
options.hasOptionalityDifferences
},targets=${JSON.stringify(options.targets)}`;
}
return `validator-state=${options.validatorState},targets=${JSON.stringify(
options.targets,
)}`;
}