From aa99de4a6bd8e1e4119cde5be98f4531d562a72d Mon Sep 17 00:00:00 2001 From: Simon Seyock Date: Fri, 16 Apr 2021 20:06:06 +0200 Subject: [PATCH] parse comment for templates --- config/jsdoc/plugins/inline-options.cjs | 68 +++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/config/jsdoc/plugins/inline-options.cjs b/config/jsdoc/plugins/inline-options.cjs index 15d7fdeeb9..ce2d12f880 100644 --- a/config/jsdoc/plugins/inline-options.cjs +++ b/config/jsdoc/plugins/inline-options.cjs @@ -5,7 +5,48 @@ * Inlines option params from typedefs */ -const properties = {}; +const docletInfos = {}; + +/** + * This parses the comment for `@template` annotations and returns an object with name / type pairs for all template + * values + * @param {string} comment a jsdoc comment to parse + * @return {Object} results + */ +function parseCommentForTemplates(comment) { + let remainingText = comment; + const results = {}; + while (true) { + const templateMatch = remainingText.match(/\* @template\s*([\s\S]*)/); + + if (!templateMatch) { + return results; + } + + remainingText = templateMatch[1]; + + let type = '*'; + + if (remainingText[0] === '{') { + let index = 1; + let openParenthesis = 1; + while (openParenthesis > 0) { + if (remainingText[index] === '{') { + openParenthesis++; + } else if (remainingText[index] === '}') { + openParenthesis--; + } + index++; + } + type = remainingText.slice(1, index - 1); + remainingText = remainingText.slice(index); + } + + const name = remainingText.match(/\s*(\S*)/)[1]; + + results[name] = type; + } +} exports.handlers = { /** @@ -14,7 +55,9 @@ exports.handlers = { */ newDoclet: function (e) { if (e.doclet.kind == 'typedef' && e.doclet.properties) { - properties[e.doclet.longname] = e.doclet.properties; + docletInfos[e.doclet.longname] = { + properties: e.doclet.properties, + }; } }, @@ -25,6 +68,16 @@ exports.handlers = { */ parseComplete: function (e) { const doclets = e.doclets; + + // gather type information + for (let i = 0, ii = doclets.length; i < ii; ++i) { + const doclet = doclets[i]; + if (doclet.longname in docletInfos) { + docletInfos[doclet.longname].type = doclet.type; + } + } + + // inline options for (let i = 0, ii = doclets.length; i < ii; ++i) { const doclet = doclets[i]; if (doclet.params) { @@ -37,13 +90,18 @@ exports.handlers = { if (genericMatches) { type = genericMatches[1]; } - if (type in properties) { - param.type.names[0] = type; + if (type in docletInfos) { + const templateInfo = parseCommentForTemplates(doclet.comment); + param.type = docletInfos[type].type; params.push.apply( params, - properties[type].map((p) => { + docletInfos[type].properties.map((p) => { const property = Object.assign({}, p); property.name = `${param.name}.${property.name}`; + if (property.type.names[0] in templateInfo) { + property.type.names[0] = + templateInfo[property.type.names[0]]; + } return property; }) );