Lawrence Forman b7b457b076
Generate (complete) solidity docs (#2391)
* `@0x/sol-doc`: New doc generator.

* `@0x/sol-compiler`: Be more tolerant of AST-only compilation targets.

* `@0x/contracts-exchange`: Add more devdoc comments.
`@0x/contracts-exchange-libs`: Add more devdoc comments.

* `@0x/sol-doc`: Update package script.

* `@0x/sol-doc`: Remove unused files and update package scripts to be easier to configure.

* Add more devdocs to contracts.

* `@0x/sol-doc`: Remove doc artifacts.

* `@0x/sol-doc`: Add `.gitignore` and `.npmignore`.

* `@0x/contracts-exchange`: Fix compilation errors.

* Fix more broken contracts.

* `@0x/contracts-erc20-bridge-sampler`: Fix failing tests.

* `@0x/contracts-asset-proxy`: Remove accidentally introduced hackathion file (lol).

* `@0x/sol-doc`: Prevent some inherited contracts from being included in docs unintentionally.

* `@0x/sol-doc`: Rename test file.

* `@0x/contracts-exchange`: Update `orderEpoch` devdoc.

* `@0x/sol-doc`: Tweak event and function docs.

* Update CODEOWNERS.

* `@0x/sol-doc` Tweak function md generation.

* `@0x/sol-doc`: add `transformDocs()` tests.

* `@0x/sol-doc`: add `extract_docs` tests.

* `@0x/sol-doc` Fix linter errors.

* `@0x/contracts-erc20-bridge-sampler`: Fix broken `ERC20BridgeSampler.sol` compile.

* `@0x/sol-doc` Fix mismatched `dev-utils` dep version.

* `@0x/sol-doc`: Add `gen_md` tests.

* `@0x/sol-doc`: Remove `fs.promises` calls.

* `@0x/sol-doc`: Fix linter errors.

* `@0x/sol-doc`: Export all relevant types and functions.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-01-03 22:59:18 -05:00

176 lines
5.0 KiB
TypeScript

import * as _ from 'lodash';
import {
ContractDocs,
ContractKind,
DocumentedItem,
EnumDocs,
EnumValueDocs,
EventDocs,
FunctionKind,
MethodDocs,
ParamDocs,
ParamDocsMap,
StateMutability,
StorageLocation,
StructDocs,
Visibility,
} from '../../src/extract_docs';
// tslint:disable: custom-no-magic-numbers completed-docs
const LETTERS = _.times(26, n => String.fromCharCode('a'.charCodeAt(0) + n));
export function randomWord(maxLength: number = 13): string {
return _.sampleSize(LETTERS, _.random(1, maxLength)).join('');
}
export function randomSentence(): string {
const numWords = _.random(3, 64);
return _.capitalize(
_.times(numWords, () => randomWord())
.join(' ')
.concat('.'),
);
}
export function randomDocs(): DocumentedItem {
return {
doc: randomSentence(),
line: _.random(1, 65536),
file: _.capitalize(randomWord()).concat('.sol'),
};
}
export function randomBoolean(): boolean {
return _.random(0, 1) === 1;
}
export function randomType(): string {
return _.sampleSize(['uint256', 'bytes32', 'bool', 'uint32', 'int256', 'int64', 'uint8'], 1)[0];
}
export function randomStorageLocation(): StorageLocation {
return _.sampleSize([StorageLocation.Default, StorageLocation.Memory, StorageLocation.Storage])[0];
}
export function randomContractKind(): ContractKind {
return _.sampleSize([ContractKind.Contract, ContractKind.Interface, ContractKind.Library])[0];
}
export function randomMutability(): StateMutability {
return _.sampleSize([
StateMutability.Nonpayable,
StateMutability.Payable,
StateMutability.Pure,
StateMutability.View,
])[0];
}
export function randomVisibility(): Visibility {
return _.sampleSize([Visibility.External, Visibility.Internal, Visibility.Public, Visibility.Private])[0];
}
export function randomFunctionKind(): FunctionKind {
return _.sampleSize([FunctionKind.Constructor, FunctionKind.Fallback, FunctionKind.Function])[0];
}
export function randomParameters(): ParamDocsMap {
const numParams = _.random(0, 7);
return _.zipObject(_.times(numParams, () => randomWord()), _.times(numParams, idx => randomParameter(idx)));
}
export function randomParameter(order: number, fields?: Partial<ParamDocs>): ParamDocs {
return {
...randomDocs(),
type: randomType(),
indexed: randomBoolean(),
storageLocation: randomStorageLocation(),
order,
...fields,
};
}
export function randomEvent(fields?: Partial<EventDocs>): EventDocs {
return {
...randomDocs(),
contract: `${randomWord()}Contract`,
name: `${randomWord()}Event`,
parameters: randomParameters(),
...fields,
};
}
export function randomMethod(fields?: Partial<MethodDocs>): MethodDocs {
return {
...randomDocs(),
contract: `${randomWord()}Contract`,
name: `${randomWord()}Method`,
kind: randomFunctionKind(),
isAccessor: randomBoolean(),
stateMutability: randomMutability(),
visibility: randomVisibility(),
returns: randomParameters(),
parameters: randomParameters(),
...fields,
};
}
export function randomStruct(fields?: Partial<StructDocs>): StructDocs {
return {
...randomDocs(),
contract: `${randomWord()}Contract`,
fields: randomParameters(),
...fields,
};
}
export function randomEnum(fields?: Partial<EnumDocs>): EnumDocs {
return {
...randomDocs(),
contract: `${randomWord()}Contract`,
values: _.mapValues(
_.groupBy(
_.times(_.random(1, 8), i => ({
...randomDocs(),
value: i,
name: randomWord(),
})),
'name',
),
v => (_.omit(v[0], 'name') as any) as EnumValueDocs,
),
...fields,
};
}
export function randomContract(contractName: string, fields?: Partial<ContractDocs>): ContractDocs {
return {
...randomDocs(),
kind: randomContractKind(),
inherits: [],
events: _.times(_.random(1, 4), () => randomEvent({ contract: contractName })),
methods: _.times(_.random(1, 4), () => randomMethod({ contract: contractName })),
structs: _.mapValues(
_.groupBy(
_.times(_.random(1, 4), () => ({
...randomStruct({ contract: contractName }),
name: `${randomWord()}Struct`,
})),
'name',
),
v => (_.omit(v[0], 'name') as any) as StructDocs,
),
enums: _.mapValues(
_.groupBy(
_.times(_.random(1, 4), () => ({
...randomEnum({ contract: contractName }),
name: `${randomWord()}Enum`,
})),
'name',
),
v => (_.omit(v[0], 'name') as any) as EnumDocs,
),
...fields,
};
}