UNPKG

solidity-docgen

Version:

Solidity API documentation automatic generator.

172 lines 6.96 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SolcAdapter = exports.compile = exports.outputSelection = void 0; const lodash_1 = require("lodash"); const fs_1 = __importDefault(require("fs")); const semver_1 = __importDefault(require("semver")); exports.outputSelection = { '*': { '': [ 'ast', ], }, }; async function compile(filter, solcModule = require.resolve('solc'), solcSettings = { optimizer: { enabled: true, runs: 200 } }) { const solc = await SolcAdapter.require(solcModule); const files = await filter.glob('*.sol'); const sources = lodash_1.fromPairs(await Promise.all(files.map(async (file) => [ file, { content: await fs_1.default.promises.readFile(file, 'utf8') }, ]))); const solcInput = { language: "Solidity", sources: sources, settings: { ...solcSettings, outputSelection: exports.outputSelection }, }; const solcOutput = solc.compile(solcInput); const { errors: allErrors } = solcOutput; if (allErrors && allErrors.some(e => e.severity === 'error')) { const errors = allErrors.filter(e => e.severity === 'error'); const firstError = errors[0].formattedMessage; const moreErrors = errors.length === 1 ? '' : ` (And ${errors.length - 1} other errors...)`; throw new Error(`Solidity was unable to compile. ${firstError}${moreErrors}`); } return solcOutput; } exports.compile = compile; class SolcAdapter { constructor(solc) { this.solc = solc; } static async require(solcModule) { const solc = await Promise.resolve().then(() => __importStar(require(solcModule))); return new SolcAdapter(solc); } compile(input) { const inputJSON = JSON.stringify(input); const solcOutputString = semver_1.default.satisfies(this.solc.version(), '>=0.6') ? this.solc.compile(inputJSON, { import: importCallback }) : this.solc.compileStandardWrapper(inputJSON, importCallback); const solcOutput = JSON.parse(solcOutputString); if (semver_1.default.satisfies(this.solc.version(), '^0.4')) { for (const source of Object.values(solcOutput.sources)) { for (const fileNode of source.ast.nodes) { if (fileNode.nodeType === 'ContractDefinition') { for (const contractNode of fileNode.nodes) { if (contractNode.nodeType === 'FunctionDefinition') { if (contractNode.isConstructor) { contractNode.kind = 'constructor'; } else if (contractNode.name === '') { contractNode.kind = 'fallback'; } else { contractNode.kind = 'function'; } } } } } } ; } const reader = new ASTReader(input, solcOutput); const adaptDocumentation = (node) => { var _a; if (typeof node.documentation === 'string') { // fix solc buggy parsing of doc comments // reverse engineered from solc behavior... node.documentation = cleanUpDocstringFromSolc(node.documentation); } else if (((_a = node.documentation) === null || _a === void 0 ? void 0 : _a.text) !== undefined) { const source = reader.read(node.documentation); if (source !== undefined) { node.documentation = cleanUpDocstringFromSource(source); } else { node.documentation = cleanUpDocstringFromSolc(node.documentation.text); } } }; for (const source of Object.values(solcOutput.sources)) { for (const fileNode of source.ast.nodes) { adaptDocumentation(fileNode); if (fileNode.nodeType === 'ContractDefinition') { for (const contractNode of fileNode.nodes) { adaptDocumentation(contractNode); } } } } return solcOutput; } } exports.SolcAdapter = SolcAdapter; function importCallback(path) { try { const resolved = require.resolve(path, { paths: ['.'] }); return { contents: fs_1.default.readFileSync(resolved, 'utf8'), }; } catch (e) { return { error: e.message, }; } } class ASTReader { constructor(input, output) { this.input = input; this.output = output; } read(node) { var _a; const { source, start, length } = this.decodeSrc(node.src); return (_a = this.input.sources[source]) === null || _a === void 0 ? void 0 : _a.content.slice(start, start + length); } decodeSrc(src) { const [start, length, sourceId] = src.split(':').map(s => parseInt(s)); const source = Object.keys(this.output.sources).find(s => this.output.sources[s].id === sourceId); if (source === undefined) { throw new Error(`No source with id ${sourceId}`); } return { source, start, length }; } } function cleanUpDocstringFromSolc(text) { // fix solc buggy parsing of doc comments // reverse engineered from solc behavior 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=solc.js.map