Update docs pipeline to solidity-docgen@0.6 (#3707)

pull/3744/head
Francisco 2 years ago committed by GitHub
parent 26dddee1c0
commit c52625018b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      contracts/governance/utils/Votes.sol
  2. 2
      contracts/token/ERC20/extensions/ERC20FlashMint.sol
  3. 4
      contracts/token/ERC20/extensions/ERC20Votes.sol
  4. 2
      contracts/token/ERC20/utils/SafeERC20.sol
  5. 2
      contracts/token/ERC721/extensions/ERC721Consecutive.sol
  6. 4
      contracts/token/ERC721/extensions/ERC721Royalty.sol
  7. 4
      contracts/token/ERC721/extensions/ERC721Votes.sol
  8. 2
      contracts/token/ERC777/ERC777.sol
  9. 4
      contracts/utils/structs/EnumerableMap.sol
  10. 21
      docs/config.js
  11. 91
      docs/contract.hbs
  12. 10
      docs/helpers.js
  13. 6
      docs/prelude.hbs
  14. 85
      docs/templates/contract.hbs
  15. 46
      docs/templates/helpers.js
  16. 4
      docs/templates/page.hbs
  17. 49
      docs/templates/properties.js
  18. 3
      hardhat.config.js
  19. 26836
      package-lock.json
  20. 9
      package.json
  21. 6
      scripts/gen-nav.js
  22. 4
      scripts/generate/templates/EnumerableMap.js
  23. 16
      scripts/prepare-docs-solc.js
  24. 12
      scripts/prepare-docs.sh

@ -122,7 +122,7 @@ abstract contract Votes is IVotes, Context, EIP712 {
/**
* @dev Delegate all of `account`'s voting units to `delegatee`.
*
* Emits events {DelegateChanged} and {DelegateVotesChanged}.
* Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
*/
function _delegate(address account, address delegatee) internal virtual {
address oldDelegate = delegates(account);

@ -73,7 +73,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
* amount + fee tokens and have them approved back to the token contract itself so
* they can be burned.
* @param receiver The receiver of the flash loan. Should implement the
* {IERC3156FlashBorrower.onFlashLoan} interface.
* {IERC3156FlashBorrower-onFlashLoan} interface.
* @param token The token to be flash loaned. Only `address(this)` is
* supported.
* @param amount The amount of tokens to be loaned.

@ -191,7 +191,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
/**
* @dev Move voting power when tokens are transferred.
*
* Emits a {DelegateVotesChanged} event.
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _afterTokenTransfer(
address from,
@ -206,7 +206,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
/**
* @dev Change delegation for `delegator` to `delegatee`.
*
* Emits events {DelegateChanged} and {DelegateVotesChanged}.
* Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
*/
function _delegate(address delegator, address delegatee) internal virtual {
address currentDelegate = delegates(delegator);

@ -104,7 +104,7 @@ library SafeERC20 {
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");

@ -78,7 +78,7 @@ abstract contract ERC721Consecutive is IERC2309, ERC721 {
*
* CAUTION: Does not invoke `onERC721Received` on the receiver.
*
* Emits a {ConsecutiveTransfer} event.
* Emits a {IERC2309-ConsecutiveTransfer} event.
*/
function _mintConsecutive(address to, uint96 batchSize) internal virtual returns (uint96) {
uint96 first = _totalConsecutiveSupply();

@ -11,8 +11,8 @@ import "../../../utils/introspection/ERC165.sol";
* @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
* information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
* Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually for
* specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to

@ -19,7 +19,7 @@ abstract contract ERC721Votes is ERC721, Votes {
/**
* @dev Adjusts votes when tokens are transferred.
*
* Emits a {Votes-DelegateVotesChanged} event.
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _afterTokenTransfer(
address from,
@ -33,7 +33,7 @@ abstract contract ERC721Votes is ERC721, Votes {
/**
* @dev Adjusts votes when a batch of tokens is transferred.
*
* Emits a {Votes-DelegateVotesChanged} event.
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _afterConsecutiveTokenTransfer(
address from,

@ -508,7 +508,7 @@ contract ERC777 is Context, IERC777, IERC20 {
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
* Might emit an {IERC20-Approval} event.
*/
function _spendAllowance(
address owner,

@ -145,10 +145,10 @@ library EnumerableMap {
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,

@ -0,0 +1,21 @@
const path = require('path');
const fs = require('fs');
/** @type import('solidity-docgen/dist/config').UserConfig */
module.exports = {
outputDir: 'docs/modules/api/pages',
templates: 'docs/templates',
exclude: ['mocks'],
pageExtension: '.adoc',
pages: (_, file, config) => {
// For each contract file, find the closest README.adoc and return its location as the output page path.
const sourcesDir = path.resolve(config.root, config.sourcesDir);
let dir = path.resolve(config.root, file.absolutePath);
while (dir.startsWith(sourcesDir)) {
dir = path.dirname(dir);
if (fs.existsSync(path.join(dir, 'README.adoc'))) {
return path.relative(sourcesDir, dir) + config.pageExtension;
}
}
},
};

@ -1,91 +0,0 @@
{{~#*inline "typed-variable-array"~}}
{{#each .}}{{typeName}}{{#if name}} {{name}}{{/if}}{{#unless @last}}, {{/unless}}{{/each}}
{{~/inline~}}
{{#each linkable}}
:{{name}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]]
{{/each}}
[.contract]
[[{{anchor}}]]
=== `++{{name}}++` link:{{github-link file.path}}[{github-icon},role=heading-link]
[.hljs-theme-light.nopadding]
```solidity
import "@openzeppelin/contracts/{{file.path}}";
```
{{natspec.devdoc}}
{{#if ownModifiers}}
[.contract-index]
.Modifiers
--
{{#each ownModifiers}}
* {xref-{{slug anchor~}} }[`++{{name}}({{args.names}})++`]
{{/each}}
--
{{/if}}
{{#if functions}}
[.contract-index]
.Functions
--
{{#each inheritedItems}}
{{#if (or @first (ne contract.name "Context"))}}
{{#unless @first}}
[.contract-subindex-inherited]
.{{contract.name}}
{{/unless}}
{{#each functions}}
* {xref-{{slug anchor~}} }[`++{{name}}({{args.names}})++`]
{{/each}}
{{/if}}
{{/each}}
--
{{/if}}
{{#if events}}
[.contract-index]
.Events
--
{{#each inheritedItems}}
{{#unless @first}}
[.contract-subindex-inherited]
.{{contract.name}}
{{/unless}}
{{#each events}}
* {xref-{{slug anchor~}} }[`++{{name}}({{args.names}})++`]
{{/each}}
{{/each}}
--
{{/if}}
{{#each ownModifiers}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{> typed-variable-array args}})++` [.item-kind]#modifier#
{{natspec.devdoc}}
{{/each}}
{{#each ownFunctions}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{> typed-variable-array args}}){{#if outputs}}{{> typed-variable-array outputs}}{{/if}}++` [.item-kind]#{{visibility}}#
{{natspec.devdoc}}
{{/each}}
{{#each ownEvents}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{> typed-variable-array args}})++` [.item-kind]#event#
{{natspec.devdoc}}
{{/each}}

@ -1,10 +0,0 @@
const { version } = require('../package.json');
module.exports = {
'github-link': (contractPath) => {
if (typeof contractPath !== 'string') {
throw new Error('Missing argument');
}
return `https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v${version}/contracts/${contractPath}`;
},
};

@ -1,6 +0,0 @@
:github-icon: pass:[<svg class="icon"><use href="#github-icon"/></svg>]
{{#links}}
:{{slug target.fullName}}: pass:normal[xref:{{path}}#{{target.anchor}}[`{{target.fullName}}`]]
:xref-{{slug target.anchor}}: xref:{{path}}#{{target.anchor}}
{{/links}}

@ -0,0 +1,85 @@
{{#each items}}
:{{name}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]]
{{/each}}
[.contract]
[[{{anchor}}]]
=== `++{{name}}++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v{{oz-version}}/{{__item_context.file.absolutePath}}[{github-icon},role=heading-link]
[.hljs-theme-light.nopadding]
```solidity
import "@openzeppelin/{{__item_context.file.absolutePath}}";
```
{{{natspec.dev}}}
{{#if modifiers}}
[.contract-index]
.Modifiers
--
{{#each modifiers}}
* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
{{/each}}
--
{{/if}}
{{#if has-functions}}
[.contract-index]
.Functions
--
{{#each inherited-functions}}
{{#unless @first}}
[.contract-subindex-inherited]
.{{contract.name}}
{{/unless}}
{{#each functions}}
* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
{{/each}}
{{/each}}
--
{{/if}}
{{#if has-events}}
[.contract-index]
.Events
--
{{#each inheritance}}
{{#unless @first}}
[.contract-subindex-inherited]
.{{name}}
{{/unless}}
{{#each events}}
* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
{{/each}}
{{/each}}
--
{{/if}}
{{#each modifiers}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}})++` [.item-kind]#modifier#
{{{natspec.dev}}}
{{/each}}
{{#each functions}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}}){{#if returns}}{{typed-params returns}}{{/if}}++` [.item-kind]#{{visibility}}#
{{{natspec.dev}}}
{{/each}}
{{#each events}}
[.contract-item]
[[{{anchor}}]]
==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}})++` [.item-kind]#event#
{{{natspec.dev}}}
{{/each}}

@ -0,0 +1,46 @@
const { version } = require('../../package.json');
module.exports['oz-version'] = () => version;
module.exports['readme-path'] = (opts) => {
return 'contracts/' + opts.data.root.id.replace(/\.adoc$/, '') + '/README.adoc';
};
module.exports.names = (params) => params.map(p => p.name).join(', ');
module.exports['typed-params'] = (params) => {
return params.map(p => `${p.type}${p.name ? ' ' + p.name : ''}`).join(', ');
};
const slug = module.exports.slug = (str) => {
if (str === undefined) {
throw new Error('Missing argument');
}
return str.replace(/\W/g, '-');
};
const linksCache = new WeakMap();
function getAllLinks (items) {
if (linksCache.has(items)) {
return linksCache.get(items);
}
const res = {};
linksCache.set(items, res);
for (const item of items) {
res[`xref-${item.anchor}`] = `xref:${item.__item_context.page}#${item.anchor}`;
res[slug(item.fullName)] = `pass:normal[xref:${item.__item_context.page}#${item.anchor}[\`${item.fullName}\`]]`;
}
return res;
}
module.exports['with-prelude'] = (opts) => {
const links = getAllLinks(opts.data.site.items);
const contents = opts.fn();
const neededLinks = contents
.match(/\{[-._a-z0-9]+\}/ig)
.map(m => m.replace(/^\{(.+)\}$/, '$1'))
.filter(k => k in links);
const prelude = neededLinks.map(k => `:${k}: ${links[k]}`).join('\n');
return prelude + '\n' + contents;
};

@ -0,0 +1,4 @@
:github-icon: pass:[<svg class="icon"><use href="#github-icon"/></svg>]
{{#with-prelude}}
{{readme (readme-path)}}
{{/with-prelude}}

@ -0,0 +1,49 @@
const { isNodeType } = require('solidity-ast/utils');
const { slug } = require('./helpers');
module.exports.anchor = function anchor ({ item, contract }) {
let res = '';
if (contract) {
res += contract.name + '-';
}
res += item.name;
if ('parameters' in item) {
const signature = item.parameters.parameters.map(v => v.typeName.typeDescriptions.typeString).join(',');
res += slug('(' + signature + ')');
}
if (isNodeType('VariableDeclaration', item)) {
res += '-' + slug(item.typeName.typeDescriptions.typeString);
}
return res;
};
module.exports.inheritance = function ({ item, build }) {
if (!isNodeType('ContractDefinition', item)) {
throw new Error('used inherited-items on non-contract');
}
return item.linearizedBaseContracts
.map(id => build.deref('ContractDefinition', id))
.filter((c, i) => c.name !== 'Context' || i === 0);
};
module.exports['has-functions'] = function ({ item }) {
return item.inheritance.some(c => c.functions.length > 0);
};
module.exports['has-events'] = function ({ item }) {
return item.inheritance.some(c => c.events.length > 0);
};
module.exports['inherited-functions'] = function ({ item }) {
const { inheritance } = item;
const baseFunctions = new Set(
inheritance.flatMap(c => c.functions.flatMap(f => f.baseFunctions ?? [])),
);
return inheritance.map((contract, i) => ({
contract,
functions: contract.functions.filter(f =>
!baseFunctions.has(f.id) && (f.name !== 'constructor' || i === 0),
),
}));
};

@ -52,6 +52,8 @@ const argv = require('yargs/yargs')()
require('@nomiclabs/hardhat-truffle5');
require('hardhat-ignore-warnings');
require('solidity-docgen');
if (argv.gas) {
require('hardhat-gas-reporter');
}
@ -95,6 +97,7 @@ module.exports = {
outputFile: argv.gasReport,
coinmarketcap: argv.coinmarketcap,
},
docgen: require('./docs/config'),
};
if (argv.coverage) {

26836
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -13,8 +13,8 @@
"scripts": {
"compile": "hardhat compile",
"coverage": "env COVERAGE=true hardhat coverage",
"docs": "oz-docs",
"docs:watch": "npm run docs watch contracts 'docs/*.hbs' docs/helpers.js",
"docs": "npm run prepare-docs && oz-docs",
"docs:watch": "oz-docs watch contracts 'docs/templates' docs/config.js",
"prepare-docs": "scripts/prepare-docs.sh",
"lint": "npm run lint:js && npm run lint:sol",
"lint:fix": "npm run lint:js:fix && npm run lint:sol:fix",
@ -56,7 +56,7 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.3",
"@nomiclabs/hardhat-truffle5": "^2.0.5",
"@nomiclabs/hardhat-web3": "^2.0.0",
"@openzeppelin/docs-utils": "^0.1.0",
"@openzeppelin/docs-utils": "^0.1.3",
"@openzeppelin/test-helpers": "^0.5.13",
"chai": "^4.2.0",
"eslint": "^7.32.0",
@ -68,6 +68,7 @@
"eth-sig-util": "^3.0.0",
"ethereumjs-util": "^7.0.7",
"ethereumjs-wallet": "^1.0.1",
"glob": "^8.0.3",
"graphlib": "^2.1.8",
"hardhat": "^2.9.1",
"hardhat-gas-reporter": "^1.0.4",
@ -84,7 +85,7 @@
"solhint": "^3.3.6",
"solidity-ast": "^0.4.25",
"solidity-coverage": "^0.8.0",
"solidity-docgen": "^0.5.3",
"solidity-docgen": "^0.6.0-beta.29",
"web3": "^1.3.0",
"yargs": "^17.0.0"
}

@ -1,14 +1,12 @@
#!/usr/bin/env node
const path = require('path');
const proc = require('child_process');
const glob = require('glob');
const startCase = require('lodash.startcase');
const baseDir = process.argv[2];
const files = proc.execFileSync(
'find', [baseDir, '-type', 'f'], { encoding: 'utf8' },
).split('\n').filter(s => s !== '');
const files = glob.sync(baseDir + '/**/*.adoc').map(f => path.relative(baseDir, f));
console.log('.API');

@ -154,10 +154,10 @@ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns
}
/**
* @dev Same as {_get}, with a custom error message when \`key\` is not in the map.
* @dev Same as {get}, with a custom error message when \`key\` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,

@ -1,16 +0,0 @@
const hre = require('hardhat');
const { getCompilersDir } = require('hardhat/internal/util/global-dir');
const { CompilerDownloader } = require('hardhat/internal/solidity/compiler/downloader');
const { Compiler } = require('hardhat/internal/solidity/compiler');
const [{ version }] = hre.config.solidity.compilers;
async function getSolc () {
const downloader = new CompilerDownloader(await getCompilersDir(), { forceSolcJs: true });
const { compilerPath } = await downloader.getDownloadedCompilerPath(version);
const compiler = new Compiler(compilerPath);
return compiler.getSolc();
}
module.exports = Object.assign(getSolc(), { __esModule: true });

@ -2,7 +2,7 @@
set -o errexit
OUTDIR=docs/modules/api/pages/
OUTDIR="$(node -p 'require("./docs/config.js").outputDir')"
if [ ! -d node_modules ]; then
npm ci
@ -10,14 +10,6 @@ fi
rm -rf "$OUTDIR"
solidity-docgen \
-t docs \
-o "$OUTDIR" \
-e contracts/mocks,contracts/examples \
--output-structure readmes \
--helpers ./docs/helpers.js \
--solc-module ./scripts/prepare-docs-solc.js
rm -f "$OUTDIR"/token/*/presets.md
hardhat docgen
node scripts/gen-nav.js "$OUTDIR" > "$OUTDIR/../nav.adoc"

Loading…
Cancel
Save