Files
openlayers/config/jsdoc/api/plugins/api.js
2019-06-17 08:15:17 +02:00

162 lines
4.3 KiB
JavaScript

/**
* Define an @api tag
* @param {Object} dictionary The tag dictionary.
*/
exports.defineTags = function(dictionary) {
dictionary.defineTag('api', {
mustHaveValue: false,
canHaveType: false,
canHaveName: false,
onTagged: function(doclet, tag) {
includeTypes(doclet);
doclet.stability = 'stable';
}
});
};
/*
* Based on @api annotations, and assuming that items with no @api annotation
* should not be documented, this plugin removes undocumented symbols
* from the documentation.
*/
const api = [];
const classes = {};
const types = {};
const modules = {};
function hasApiMembers(doclet) {
return doclet.longname.split('#')[0] == this.longname;
}
function includeAugments(doclet) {
const augments = doclet.augments;
if (augments) {
let cls;
for (let i = augments.length - 1; i >= 0; --i) {
cls = classes[augments[i]];
if (cls) {
includeAugments(cls);
if (cls.fires) {
if (!doclet.fires) {
doclet.fires = [];
}
cls.fires.forEach(function(f) {
if (doclet.fires.indexOf(f) == -1) {
doclet.fires.push(f);
}
});
}
if (cls.observables) {
if (!doclet.observables) {
doclet.observables = [];
}
cls.observables.forEach(function(f) {
if (doclet.observables.indexOf(f) == -1) {
doclet.observables.push(f);
}
});
}
cls._hideConstructor = true;
if (!cls.undocumented) {
cls._documented = true;
}
}
}
}
}
function extractTypes(item) {
item.type.names.forEach(function(type) {
const match = type.match(/^(.*<)?([^>]*)>?$/);
if (match) {
modules[match[2]] = true;
types[match[2]] = true;
}
});
}
function includeTypes(doclet) {
if (doclet.params) {
doclet.params.forEach(extractTypes);
}
if (doclet.returns) {
doclet.returns.forEach(extractTypes);
}
if (doclet.properties) {
doclet.properties.forEach(extractTypes);
}
if (doclet.type && doclet.meta.code.type == 'MemberExpression') {
extractTypes(doclet);
}
}
exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.stability) {
modules[doclet.longname.split(/[~\.]/).shift()] = true;
api.push(doclet);
}
if (doclet.kind == 'class') {
modules[doclet.longname.split(/[~\.]/).shift()] = true;
if (!(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
} else if ('augments' in doclet) {
classes[doclet.longname].augments = doclet.augments;
}
}
if (doclet.name === doclet.longname && !doclet.memberof) {
// Make sure anonymous default exports are documented
doclet.setMemberof(doclet.longname);
}
},
parseComplete: function(e) {
const doclets = e.doclets;
for (let i = doclets.length - 1; i >= 0; --i) {
const doclet = doclets[i];
if (doclet.stability) {
if (doclet.kind == 'class') {
includeAugments(doclet);
}
if (doclet.fires) {
doclet.fires.sort(function(a, b) {
return a.split(/#?event:/)[1] < b.split(/#?event:/)[1] ? -1 : 1;
});
}
if (doclet.observables) {
doclet.observables.sort(function(a, b) {
return a.name < b.name ? -1 : 1;
});
}
// Always document namespaces and items with stability annotation
continue;
}
if (doclet.kind == 'module' && doclet.longname in modules) {
// Document all modules that are referenced by the API
continue;
}
if (doclet.isEnum || doclet.kind == 'typedef') {
continue;
}
if (doclet.kind == 'class' && api.some(hasApiMembers, doclet)) {
// Mark undocumented classes with documented members as unexported.
// This is used in ../template/tmpl/container.tmpl to hide the
// constructor from the docs.
doclet._hideConstructor = true;
includeAugments(doclet);
} else if (doclet.undocumented !== false && !doclet._hideConstructor && !(doclet.kind == 'typedef' && doclet.longname in types)) {
// Remove all other undocumented symbols
doclet.undocumented = true;
}
if (doclet._documented) {
delete doclet.undocumented;
}
}
}
};