UNPKG

solidity-docgen

Version:

Documentation generator for Solidity smart contracts.

117 lines 5.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseNatspec = void 0; const utils_1 = require("solidity-ast/utils"); const site_1 = require("../site"); const arrays_equal_1 = require("./arrays-equal"); const execall_1 = require("./execall"); const item_type_1 = require("./item-type"); const ItemError_1 = require("./ItemError"); const read_item_docs_1 = require("./read-item-docs"); const scope_1 = require("./scope"); function parseNatspec(item) { var _a; if (!item[site_1.DOC_ITEM_CONTEXT]) throw new Error(`Not an item or item is missing context`); let res = {}; const docSource = (0, read_item_docs_1.readItemDocs)(item); const docString = docSource !== undefined ? cleanUpDocstringFromSource(docSource) : 'documentation' in item && item.documentation ? typeof item.documentation === 'string' ? item.documentation : cleanUpDocstringFromSolc(item.documentation.text) : ''; const tagMatches = (0, execall_1.execAll)(/^(?:@(\w+|custom:[a-z][a-z-]*) )?((?:(?!^@(?:\w+|custom:[a-z][a-z-]*) )[^])*)/m, docString); let inheritFrom; for (const [, tag = 'notice', content] of tagMatches) { if (content === undefined) throw new ItemError_1.ItemError('Unexpected error', item); if (tag === 'dev' || tag === 'notice') { res[tag] ?? (res[tag] = ''); res[tag] += content; } if (tag === 'title') { res.title = content.trim(); } if (tag === 'param') { const paramMatches = content.match(/(\w+) ([^]*)/); if (paramMatches) { const [, name, description] = paramMatches; res.params ?? (res.params = []); res.params.push({ name, description: description.trim() }); } } if (tag === 'return') { if (!('returnParameters' in item)) { throw new ItemError_1.ItemError(`Item does not contain return parameters`, item); } res.returns ?? (res.returns = []); const i = res.returns.length; const p = item.returnParameters.parameters[i]; if (p === undefined) { throw new ItemError_1.ItemError('Got more @return tags than expected', item); } if (!p.name) { res.returns.push({ description: content.trim() }); } else { const paramMatches = content.match(/(\w+)( ([^]*))?/); if (!paramMatches || paramMatches[1] !== p.name) { throw new ItemError_1.ItemError(`Expected @return tag to start with name '${p.name}'`, item); } const [, name, description] = paramMatches; res.returns.push({ name, description: description?.trim() ?? '' }); } } if (tag?.startsWith('custom:')) { const key = tag.replace(/^custom:/, ''); res.custom ?? (res.custom = {}); (_a = res.custom)[key] ?? (_a[key] = ''); res.custom[key] += content; } if (tag === 'inheritdoc') { if (!(item.nodeType === 'FunctionDefinition' || item.nodeType === 'VariableDeclaration')) { throw new ItemError_1.ItemError(`Expected function or variable but saw ${(0, item_type_1.itemType)(item)}`, item); } const parentContractName = content.trim(); const parentContract = (0, scope_1.getContractsInScope)(item)[parentContractName]; if (!parentContract) { throw new ItemError_1.ItemError(`Parent contract '${parentContractName}' not found`, item); } inheritFrom = [...(0, utils_1.findAll)('FunctionDefinition', parentContract)].find(f => item.baseFunctions?.includes(f.id)); } } if (docString.length === 0) { if ('baseFunctions' in item && item.baseFunctions?.length === 1) { const baseFn = item[site_1.DOC_ITEM_CONTEXT].build.deref('FunctionDefinition', item.baseFunctions[0]); const shouldInherit = item.nodeType === 'VariableDeclaration' || (0, arrays_equal_1.arraysEqual)(item.parameters.parameters, baseFn.parameters.parameters, p => p.name); if (shouldInherit) { inheritFrom = baseFn; } } } if (res.dev) res.dev = res.dev.trim(); if (res.notice) res.notice = res.notice.trim(); if (inheritFrom) { res = { ...parseNatspec(inheritFrom), ...res }; } return res; } exports.parseNatspec = parseNatspec; // Fix solc buggy parsing of doc comments. // Reverse engineered from solc behavior. function cleanUpDocstringFromSolc(text) { return text .replace(/\n\n?^[ \t]*(?:\*|\/\/\/)/mg, '\n\n') .replace(/^[ \t]?/mg, ''); } function cleanUpDocstringFromSource(text) { return text .replace(/^\/\*\*(.*)\*\/$/s, '$1') .trim() .replace(/^[ \t]*(\*|\/\/\/)[ \t]?/mg, ''); } //# sourceMappingURL=natspec.js.map