aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts/utils/typedoc_utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website/ts/utils/typedoc_utils.ts')
-rw-r--r--packages/website/ts/utils/typedoc_utils.ts356
1 files changed, 356 insertions, 0 deletions
diff --git a/packages/website/ts/utils/typedoc_utils.ts b/packages/website/ts/utils/typedoc_utils.ts
new file mode 100644
index 000000000..b3d0f7d90
--- /dev/null
+++ b/packages/website/ts/utils/typedoc_utils.ts
@@ -0,0 +1,356 @@
+import * as _ from 'lodash';
+import compareVersions = require('compare-versions');
+import {constants} from 'ts/utils/constants';
+import {utils} from 'ts/utils/utils';
+import {
+ TypeDocNode,
+ KindString,
+ ZeroExJsDocSections,
+ MenuSubsectionsBySection,
+ TypeDocType,
+ Type,
+ DocAgnosticFormat,
+ DocSection,
+ TypescriptMethod,
+ Parameter,
+ Property,
+ CustomType,
+ IndexSignature,
+ CustomTypeChild,
+ TypeParameter,
+ TypeDocTypes,
+} from 'ts/types';
+
+const TYPES_MODULE_PATH = '"src/types"';
+
+export const sectionNameToPossibleModulePaths: {[name: string]: string[]} = {
+ [ZeroExJsDocSections.zeroEx]: ['"src/0x"'],
+ [ZeroExJsDocSections.exchange]: ['"src/contract_wrappers/exchange_wrapper"'],
+ [ZeroExJsDocSections.tokenRegistry]: ['"src/contract_wrappers/token_registry_wrapper"'],
+ [ZeroExJsDocSections.token]: ['"src/contract_wrappers/token_wrapper"'],
+ [ZeroExJsDocSections.etherToken]: ['"src/contract_wrappers/ether_token_wrapper"'],
+ [ZeroExJsDocSections.proxy]: [
+ '"src/contract_wrappers/proxy_wrapper"',
+ '"src/contract_wrappers/token_transfer_proxy_wrapper"',
+ ],
+ [ZeroExJsDocSections.types]: [TYPES_MODULE_PATH],
+};
+
+export const typeDocUtils = {
+ isType(entity: TypeDocNode): boolean {
+ return entity.kindString === KindString.Interface ||
+ entity.kindString === KindString.Function ||
+ entity.kindString === KindString['Type alias'] ||
+ entity.kindString === KindString.Variable ||
+ entity.kindString === KindString.Enumeration;
+ },
+ isMethod(entity: TypeDocNode): boolean {
+ return entity.kindString === KindString.Method;
+ },
+ isConstructor(entity: TypeDocNode): boolean {
+ return entity.kindString === KindString.Constructor;
+ },
+ isProperty(entity: TypeDocNode): boolean {
+ return entity.kindString === KindString.Property;
+ },
+ isPrivateOrProtectedProperty(propertyName: string): boolean {
+ return _.startsWith(propertyName, '_');
+ },
+ isPublicType(typeName: string): boolean {
+ return _.includes(constants.public0xjsTypes, typeName);
+ },
+ getModuleDefinitionBySectionNameIfExists(versionDocObj: TypeDocNode, sectionName: string):
+ TypeDocNode|undefined {
+ const possibleModulePathNames = sectionNameToPossibleModulePaths[sectionName];
+ const modules = versionDocObj.children;
+ for (const mod of modules) {
+ if (_.includes(possibleModulePathNames, mod.name)) {
+ const moduleWithName = mod;
+ return moduleWithName;
+ }
+ }
+ return undefined;
+ },
+ getMenuSubsectionsBySection(docAgnosticFormat?: DocAgnosticFormat): MenuSubsectionsBySection {
+ const menuSubsectionsBySection = {} as MenuSubsectionsBySection;
+ if (_.isUndefined(docAgnosticFormat)) {
+ return menuSubsectionsBySection;
+ }
+
+ const docSections = _.keys(ZeroExJsDocSections);
+ _.each(docSections, sectionName => {
+ const docSection = docAgnosticFormat[sectionName];
+ if (_.isUndefined(docSection)) {
+ return; // no-op
+ }
+
+ if (sectionName === ZeroExJsDocSections.types) {
+ const typeNames = _.map(docSection.types, t => t.name);
+ menuSubsectionsBySection[sectionName] = typeNames;
+ } else {
+ const methodNames = _.map(docSection.methods, m => m.name);
+ menuSubsectionsBySection[sectionName] = methodNames;
+ }
+ });
+ return menuSubsectionsBySection;
+ },
+ getFinal0xjsMenu(selectedVersion: string): {[section: string]: string[]} {
+ const finalMenu = _.cloneDeep(constants.menu0xjs);
+ finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => {
+ const versionIntroducedIfExists = constants.menuSubsectionToVersionWhenIntroduced[contractName];
+ if (!_.isUndefined(versionIntroducedIfExists)) {
+ const existsInSelectedVersion = compareVersions(selectedVersion,
+ versionIntroducedIfExists) >= 0;
+ return existsInSelectedVersion;
+ } else {
+ return true;
+ }
+ });
+ return finalMenu;
+ },
+ convertToDocAgnosticFormat(typeDocJson: TypeDocNode): DocAgnosticFormat {
+ const subMenus = _.values(constants.menu0xjs);
+ const orderedSectionNames = _.flatten(subMenus);
+ const docAgnosticFormat: DocAgnosticFormat = {};
+ _.each(orderedSectionNames, sectionName => {
+ const packageDefinitionIfExists = typeDocUtils.getModuleDefinitionBySectionNameIfExists(
+ typeDocJson, sectionName,
+ );
+ if (_.isUndefined(packageDefinitionIfExists)) {
+ return; // no-op
+ }
+
+ // Since the `types.ts` file is the only file that does not export a module/class but
+ // instead has each type export itself, we do not need to go down two levels of nesting
+ // for it.
+ let entities;
+ let packageComment = '';
+ if (sectionName === ZeroExJsDocSections.types) {
+ entities = packageDefinitionIfExists.children;
+ } else {
+ entities = packageDefinitionIfExists.children[0].children;
+ const commentObj = packageDefinitionIfExists.children[0].comment;
+ packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment;
+ }
+
+ const docSection = typeDocUtils._convertEntitiesToDocSection(entities, sectionName);
+ docSection.comment = packageComment;
+ docAgnosticFormat[sectionName] = docSection;
+ });
+ return docAgnosticFormat;
+ },
+ _convertEntitiesToDocSection(entities: TypeDocNode[], sectionName: string) {
+ const docSection: DocSection = {
+ comment: '',
+ constructors: [],
+ methods: [],
+ properties: [],
+ types: [],
+ };
+
+ let isConstructor;
+ _.each(entities, entity => {
+ switch (entity.kindString) {
+ case KindString.Constructor:
+ isConstructor = true;
+ const constructor = typeDocUtils._convertMethod(entity, isConstructor, sectionName);
+ docSection.constructors.push(constructor);
+ break;
+
+ case KindString.Method:
+ if (entity.flags.isPublic) {
+ isConstructor = false;
+ const method = typeDocUtils._convertMethod(entity, isConstructor, sectionName);
+ docSection.methods.push(method);
+ }
+ break;
+
+ case KindString.Property:
+ if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) {
+ const property = typeDocUtils._convertProperty(entity, sectionName);
+ docSection.properties.push(property);
+ }
+ break;
+
+ case KindString.Interface:
+ case KindString.Function:
+ case KindString.Variable:
+ case KindString.Enumeration:
+ case KindString['Type alias']:
+ if (typeDocUtils.isPublicType(entity.name)) {
+ const customType = typeDocUtils._convertCustomType(entity, sectionName);
+ docSection.types.push(customType);
+ }
+ break;
+
+ default:
+ throw utils.spawnSwitchErr('kindString', entity.kindString);
+ }
+ });
+ return docSection;
+ },
+ _convertCustomType(entity: TypeDocNode, sectionName: string): CustomType {
+ const typeIfExists = !_.isUndefined(entity.type) ?
+ typeDocUtils._convertType(entity.type, sectionName) :
+ undefined;
+ const isConstructor = false;
+ const methodIfExists = !_.isUndefined(entity.declaration) ?
+ typeDocUtils._convertMethod(entity.declaration, isConstructor, sectionName) :
+ undefined;
+ const indexSignatureIfExists = !_.isUndefined(entity.indexSignature) ?
+ typeDocUtils._convertIndexSignature(entity.indexSignature[0], sectionName) :
+ undefined;
+ const commentIfExists = !_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText) ?
+ entity.comment.shortText :
+ undefined;
+
+ const childrenIfExist = !_.isUndefined(entity.children) ?
+ _.map(entity.children, (child: TypeDocNode) => {
+ const childTypeIfExists = !_.isUndefined(child.type) ?
+ typeDocUtils._convertType(child.type, sectionName) :
+ undefined;
+ const c: CustomTypeChild = {
+ name: child.name,
+ type: childTypeIfExists,
+ defaultValue: child.defaultValue,
+ };
+ return c;
+ }) :
+ undefined;
+
+ const customType = {
+ name: entity.name,
+ kindString: entity.kindString,
+ type: typeIfExists,
+ method: methodIfExists,
+ indexSignature: indexSignatureIfExists,
+ defaultValue: entity.defaultValue,
+ comment: commentIfExists,
+ children: childrenIfExist,
+ };
+ return customType;
+ },
+ _convertIndexSignature(entity: TypeDocNode, sectionName: string): IndexSignature {
+ const key = entity.parameters[0];
+ const indexSignature = {
+ keyName: key.name,
+ keyType: typeDocUtils._convertType(key.type, sectionName),
+ valueName: entity.type.name,
+ };
+ return indexSignature;
+ },
+ _convertProperty(entity: TypeDocNode, sectionName: string): Property {
+ const source = entity.sources[0];
+ const commentIfExists = !_.isUndefined(entity.comment) ? entity.comment.shortText : undefined;
+ const property = {
+ name: entity.name,
+ type: typeDocUtils._convertType(entity.type, sectionName),
+ source: {
+ fileName: source.fileName,
+ line: source.line,
+ },
+ comment: commentIfExists,
+ };
+ return property;
+ },
+ _convertMethod(entity: TypeDocNode, isConstructor: boolean, sectionName: string): TypescriptMethod {
+ const signature = entity.signatures[0];
+ const source = entity.sources[0];
+ const hasComment = !_.isUndefined(signature.comment);
+ const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic;
+
+ const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.';
+ // HACK: we use the fact that the sectionName is the same as the property name at the top-level
+ // of the public interface. In the future, we shouldn't use this hack but rather get it from the JSON.
+ let callPath = (sectionName !== ZeroExJsDocSections.zeroEx) ?
+ `${topLevelInterface}${sectionName}.` :
+ topLevelInterface;
+ callPath = isConstructor ? '' : callPath;
+
+ const parameters = _.map(signature.parameters, param => {
+ return typeDocUtils._convertParameter(param, sectionName);
+ });
+ const returnType = typeDocUtils._convertType(signature.type, sectionName);
+ const typeParameter = _.isUndefined(signature.typeParameter) ?
+ undefined :
+ typeDocUtils._convertTypeParameter(signature.typeParameter[0], sectionName);
+
+ const method = {
+ isConstructor,
+ isStatic,
+ name: signature.name,
+ comment: hasComment ? signature.comment.shortText : undefined,
+ returnComment: hasComment && signature.comment.returns ? signature.comment.returns : undefined,
+ source: {
+ fileName: source.fileName,
+ line: source.line,
+ },
+ callPath,
+ parameters,
+ returnType,
+ typeParameter,
+ };
+ return method;
+ },
+ _convertTypeParameter(entity: TypeDocNode, sectionName: string): TypeParameter {
+ const type = typeDocUtils._convertType(entity.type, sectionName);
+ const parameter = {
+ name: entity.name,
+ type,
+ };
+ return parameter;
+ },
+ _convertParameter(entity: TypeDocNode, sectionName: string): Parameter {
+ let comment = '<No comment>';
+ if (entity.comment && entity.comment.shortText) {
+ comment = entity.comment.shortText;
+ } else if (entity.comment && entity.comment.text) {
+ comment = entity.comment.text;
+ }
+
+ const isOptional = !_.isUndefined(entity.flags.isOptional) ?
+ entity.flags.isOptional :
+ false;
+
+ const type = typeDocUtils._convertType(entity.type, sectionName);
+
+ const parameter = {
+ name: entity.name,
+ comment,
+ isOptional,
+ type,
+ };
+ return parameter;
+ },
+ _convertType(entity: TypeDocType, sectionName: string): Type {
+ const typeArguments = _.map(entity.typeArguments, typeArgument => {
+ return typeDocUtils._convertType(typeArgument, sectionName);
+ });
+ const types = _.map(entity.types, t => {
+ return typeDocUtils._convertType(t, sectionName);
+ });
+
+ const isConstructor = false;
+ const methodIfExists = !_.isUndefined(entity.declaration) ?
+ typeDocUtils._convertMethod(entity.declaration, isConstructor, sectionName) :
+ undefined;
+
+ const elementTypeIfExists = !_.isUndefined(entity.elementType) ?
+ {
+ name: entity.elementType.name,
+ typeDocType: entity.elementType.type,
+ } :
+ undefined;
+
+ const type = {
+ name: entity.name,
+ value: entity.value,
+ typeDocType: entity.type,
+ typeArguments,
+ elementType: elementTypeIfExists,
+ types,
+ method: methodIfExists,
+ };
+ return type;
+ },
+};