@custom-elements-manifest/analyzer
Version:
<!-- [=> See Source <=](../../docs/analyzer/index.md) -->
195 lines (166 loc) • 5.06 kB
JavaScript
/**
* UTILITIES RELATED TO GETTING INFORMATION OUT OF A MANIFEST OR DOC
*/
import { has } from "./index.js";
/**
* @typedef {import('custom-elements-manifest/schema').Package} Package
*/
function loopThroughDeclarations(manifest, predicate) {
manifest?.modules?.forEach(_module => {
_module?.declarations?.forEach(predicate);
});
}
function loopThroughExports(manifest, predicate) {
manifest?.modules?.forEach(_module => {
_module?.exports?.forEach(predicate);
});
}
/**
* Loops through all modules' exports, and returns the kind provided by the users
*
* @example getKind('class');
* @example getKind('custom-element-definition');
*/
export function getAllExportsOfKind(manifest, kind) {
const result = [];
loopThroughExports(manifest, (_export) => {
if(_export.kind === kind) {
result.push(_export);
}
});
return result;
}
/**
* Loops through all modules' declarations, and returns the kind provided by the users
*
* @example getKind('class');
* @example getKind('custom-element-definition');
*/
export function getAllDeclarationsOfKind(manifest, kind) {
const result = [];
loopThroughDeclarations(manifest, (declaration) => {
if(declaration.kind === kind) {
result.push(declaration);
}
});
return result;
}
/**
* Gets the inheritance tree from a manifest given a className
* Returns an array of a classes mixins/superclasses all the way up the chain
*
* @param {Package[]} manifests
* @param {string} className
*/
export function getInheritanceTree(manifests, className) {
const tree = [];
const allClassLikes = new Map();
const _classes = [];
const _mixins = [];
manifests.forEach((cem) => {
_classes.push(...getAllDeclarationsOfKind(cem, 'class'));
_mixins.push(...getAllDeclarationsOfKind(cem, 'mixin'));
});
[..._mixins, ..._classes].forEach((klass) => {
allClassLikes.set(klass.name, klass);
});
let klass = allClassLikes.get(className)
if(klass) {
tree.push(klass)
klass?.mixins?.forEach(mixin => {
let foundMixin = _mixins.find(m => m.name === mixin.name);
if(foundMixin) {
tree.push(foundMixin);
while(has(foundMixin?.mixins)) {
foundMixin?.mixins?.forEach(mixin => {
foundMixin = _mixins.find(m => m.name === mixin.name);
if(foundMixin) {
tree.push(foundMixin);
}
});
}
}
});
while(allClassLikes.has(klass.superclass?.name)) {
const newKlass = allClassLikes.get(klass.superclass.name);
let allMixins = [];
if (klass?.mixins) {
allMixins = [...klass.mixins];
}
if (newKlass?.mixins) {
allMixins = [...allMixins, ...newKlass.mixins];
}
allMixins.forEach(mixin => {
let foundMixin = _mixins.find(m => m.name === mixin.name);
if(foundMixin) {
tree.push(foundMixin);
while(has(foundMixin?.mixins)) {
foundMixin?.mixins?.forEach(mixin => {
foundMixin = _mixins.find(m => m.name === mixin.name);
if(foundMixin) {
tree.push(foundMixin);
}
});
}
}
});
tree.push(newKlass);
klass = newKlass;
}
return tree;
}
return [];
}
/**
* @param {Package[]} manifests
* @param {string} modulePath
*/
export function getModuleFromManifests(manifests, modulePath) {
let result = undefined;
manifests.forEach((cem) => {
cem?.modules?.forEach((_module) => {
if (_module.path === modulePath) {
result = _module;
}
});
});
return result;
}
/**
* @param {Package[]} manifests
* @param {string} className
*/
export function getModuleForClassLike(manifests, className) {
let result = undefined;
manifests.forEach((cem) => {
cem?.modules?.forEach(_module => {
_module?.declarations?.forEach(declaration => {
if((declaration.kind === 'class' || declaration.kind === 'mixin') && declaration.name === className) {
result = _module.path;
}
});
});
});
return result;
}
/**
* Given a manifest module, a class name, and a class member name, gets the
* manifest doc for the module's class' member.
*
* @param {Partial<import('custom-elements-manifest/schema').Module>} moduleDoc Manifest module
* @param {string} className Class to get member of
* @param {string} memberName Class member to get
* @param {boolean} isStatic Is it a static member?
* @return {import('custom-elements-manifest/schema').ClassMember|void} the requested class member
*/
export function getClassMemberDoc(moduleDoc, className, memberName, isStatic = false) {
/** @type {import('custom-elements-manifest/schema').ClassDeclaration} */
const classDoc = (moduleDoc.declarations.find(x => x.name === className));
if (!classDoc || !has(classDoc.members))
return;
const memberDoc = classDoc.members.find(x =>
x.name === memberName &&
(x.static ?? false) === isStatic
);
return memberDoc;
}