diff options
author | Fabio Berger <me@fabioberger.com> | 2018-03-09 15:39:38 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-03-09 15:39:38 +0800 |
commit | 9699ee4eff8a6594bd862883cac35de80dfbcf56 (patch) | |
tree | 01c5a092bd0180101dcc012e3d21320d9addb073 /packages/react-docs/src/ts/utils | |
parent | da277f5b2743c666a9a66e4fadf6678edd44fd69 (diff) | |
parent | 0eeaac1f2b5095441f7cd04bc948515d600d1f3a (diff) | |
download | dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar.gz dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar.bz2 dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar.lz dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar.xz dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.tar.zst dexon-0x-contracts-9699ee4eff8a6594bd862883cac35de80dfbcf56.zip |
Merge branch 'development' into addPackagePublishConfig
* development: (94 commits)
Update CHANGELOG
Add solc 0.4.20 and 0.4.21
Prettier sra-report README
Add new packages to top level README
Updated @0xproject/utils in top level package.json
Publish
Updated CHANGELOGs
Detail tests in the README
Add support for ropsten and rinkeby
Fix yarn.lock
Update list of packages and organize them alphabetically
Fix prettier issues
Add support for going back to previous hashes via the browser back button to wiki
Scroll to previous hashed elements when user clicks back button
Add back strict null checks to react-shared package and fix issues
remove ability to have implicit dependencies and add missing deps
update license
remove no-implicit-this
Add example & screenshot to npmignore
Remove `;` to be nice to windows users
...
Diffstat (limited to 'packages/react-docs/src/ts/utils')
-rw-r--r-- | packages/react-docs/src/ts/utils/constants.ts | 9 | ||||
-rw-r--r-- | packages/react-docs/src/ts/utils/doxity_utils.ts | 175 | ||||
-rw-r--r-- | packages/react-docs/src/ts/utils/typedoc_utils.ts | 370 | ||||
-rw-r--r-- | packages/react-docs/src/ts/utils/utils.ts | 10 |
4 files changed, 564 insertions, 0 deletions
diff --git a/packages/react-docs/src/ts/utils/constants.ts b/packages/react-docs/src/ts/utils/constants.ts new file mode 100644 index 000000000..c3c74fd11 --- /dev/null +++ b/packages/react-docs/src/ts/utils/constants.ts @@ -0,0 +1,9 @@ +import { SupportedDocJson } from '../types'; + +export const constants = { + TYPES_SECTION_NAME: 'types', + TYPE_TO_SYNTAX: { + [SupportedDocJson.Doxity]: 'solidity', + [SupportedDocJson.TypeDoc]: 'typescript', + } as { [supportedDocType: string]: string }, +}; diff --git a/packages/react-docs/src/ts/utils/doxity_utils.ts b/packages/react-docs/src/ts/utils/doxity_utils.ts new file mode 100644 index 000000000..26dea6966 --- /dev/null +++ b/packages/react-docs/src/ts/utils/doxity_utils.ts @@ -0,0 +1,175 @@ +import * as _ from 'lodash'; + +import { + AbiTypes, + DocAgnosticFormat, + DocSection, + DoxityAbiDoc, + DoxityContractObj, + DoxityDocObj, + DoxityInput, + EventArg, + Parameter, + Property, + SolidityMethod, + Type, + TypeDocTypes, +} from '../types'; + +export const doxityUtils = { + convertToDocAgnosticFormat(doxityDocObj: DoxityDocObj): DocAgnosticFormat { + const docAgnosticFormat: DocAgnosticFormat = {}; + _.each(doxityDocObj, (doxityContractObj: DoxityContractObj, contractName: string) => { + const doxityConstructor = _.find(doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => { + return abiDoc.type === AbiTypes.Constructor; + }); + const constructors = []; + if (!_.isUndefined(doxityConstructor)) { + const constructor = { + isConstructor: true, + name: doxityContractObj.name, + comment: doxityConstructor.details, + returnComment: doxityConstructor.return, + callPath: '', + parameters: this._convertParameters(doxityConstructor.inputs), + returnType: this._convertType(doxityContractObj.name), + }; + constructors.push(constructor); + } + + const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( + doxityContractObj.abiDocs, + (abiDoc: DoxityAbiDoc) => { + return this._isMethod(abiDoc); + }, + ); + const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>( + doxityMethods, + (doxityMethod: DoxityAbiDoc) => { + const outputs = !_.isUndefined(doxityMethod.outputs) ? doxityMethod.outputs : []; + let returnTypeIfExists: Type; + if (outputs.length === 0) { + // no-op. It's already undefined + } else if (outputs.length === 1) { + const outputsType = outputs[0].type; + returnTypeIfExists = this._convertType(outputsType); + } else { + const outputsType = `[${_.map(outputs, output => output.type).join(', ')}]`; + returnTypeIfExists = this._convertType(outputsType); + } + // For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken + const callPath = + contractName !== 'ZRXToken' + ? `${contractName[0].toLowerCase()}${contractName.slice(1)}.` + : `${contractName.slice(0, 3).toLowerCase()}${contractName.slice(3)}.`; + const method = { + isConstructor: false, + isConstant: doxityMethod.constant, + isPayable: doxityMethod.payable, + name: doxityMethod.name, + comment: doxityMethod.details, + returnComment: doxityMethod.return, + callPath, + parameters: this._convertParameters(doxityMethod.inputs), + returnType: returnTypeIfExists, + }; + return method; + }, + ); + + const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( + doxityContractObj.abiDocs, + (abiDoc: DoxityAbiDoc) => { + return this._isProperty(abiDoc); + }, + ); + const properties = _.map<DoxityAbiDoc, Property>(doxityProperties, (doxityProperty: DoxityAbiDoc) => { + // We assume that none of our functions return more then a single return value + let typeName = doxityProperty.outputs[0].type; + if (!_.isEmpty(doxityProperty.inputs)) { + // Properties never have more then a single input + typeName = `(${doxityProperty.inputs[0].type} => ${typeName})`; + } + const property = { + name: doxityProperty.name, + type: this._convertType(typeName), + comment: doxityProperty.details, + }; + return property; + }); + + const doxityEvents = _.filter( + doxityContractObj.abiDocs, + (abiDoc: DoxityAbiDoc) => abiDoc.type === AbiTypes.Event, + ); + const events = _.map(doxityEvents, doxityEvent => { + const event = { + name: doxityEvent.name, + eventArgs: this._convertEventArgs(doxityEvent.inputs), + }; + return event; + }); + + const docSection: DocSection = { + comment: doxityContractObj.title, + constructors, + methods, + properties, + types: [], + events, + }; + docAgnosticFormat[contractName] = docSection; + }); + return docAgnosticFormat; + }, + _convertParameters(inputs: DoxityInput[]): Parameter[] { + const parameters = _.map(inputs, input => { + const parameter = { + name: input.name, + comment: input.description, + isOptional: false, + type: this._convertType(input.type), + }; + return parameter; + }); + return parameters; + }, + _convertType(typeName: string): Type { + const type = { + name: typeName, + typeDocType: TypeDocTypes.Intrinsic, + }; + return type; + }, + _isMethod(abiDoc: DoxityAbiDoc) { + if (abiDoc.type !== AbiTypes.Function) { + return false; + } + const hasInputs = !_.isEmpty(abiDoc.inputs); + const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name); + const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase(); + const isMethod = hasNamedOutputIfExists && !isNameAllCaps; + return isMethod; + }, + _isProperty(abiDoc: DoxityAbiDoc) { + if (abiDoc.type !== AbiTypes.Function) { + return false; + } + const hasInputs = !_.isEmpty(abiDoc.inputs); + const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name); + const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase(); + const isProperty = !hasNamedOutputIfExists || isNameAllCaps; + return isProperty; + }, + _convertEventArgs(inputs: DoxityInput[]): EventArg[] { + const eventArgs = _.map(inputs, input => { + const eventArg = { + isIndexed: input.indexed, + name: input.name, + type: this._convertType(input.type), + }; + return eventArg; + }); + return eventArgs; + }, +}; diff --git a/packages/react-docs/src/ts/utils/typedoc_utils.ts b/packages/react-docs/src/ts/utils/typedoc_utils.ts new file mode 100644 index 000000000..e4cea1e40 --- /dev/null +++ b/packages/react-docs/src/ts/utils/typedoc_utils.ts @@ -0,0 +1,370 @@ +import * as _ from 'lodash'; + +import { DocsInfo } from '../docs_info'; +import { + CustomType, + CustomTypeChild, + DocAgnosticFormat, + DocSection, + IndexSignature, + KindString, + Parameter, + Property, + SectionsMap, + Type, + TypeDocNode, + TypeDocType, + TypeParameter, + TypescriptMethod, +} from '../types'; +import { utils } from '../utils/utils'; + +export const typeDocUtils = { + isType(entity: TypeDocNode): boolean { + return ( + entity.kindString === KindString.Interface || + entity.kindString === KindString.Function || + entity.kindString === KindString.TypeAlias || + 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, '_'); + }, + getModuleDefinitionsBySectionName(versionDocObj: TypeDocNode, configModulePaths: string[]): TypeDocNode[] { + const moduleDefinitions: TypeDocNode[] = []; + const jsonModules = versionDocObj.children; + _.each(jsonModules, jsonMod => { + _.each(configModulePaths, configModulePath => { + if (_.includes(configModulePath, jsonMod.name)) { + moduleDefinitions.push(jsonMod); + } + }); + }); + return moduleDefinitions; + }, + convertToDocAgnosticFormat(typeDocJson: TypeDocNode, docsInfo: DocsInfo): DocAgnosticFormat { + const subMenus = _.values(docsInfo.getMenu()); + const orderedSectionNames = _.flatten(subMenus); + const docAgnosticFormat: DocAgnosticFormat = {}; + _.each(orderedSectionNames, sectionName => { + const modulePathsIfExists = docsInfo.getModulePathsIfExists(sectionName); + if (_.isUndefined(modulePathsIfExists)) { + return; // no-op + } + const packageDefinitions = typeDocUtils.getModuleDefinitionsBySectionName(typeDocJson, modulePathsIfExists); + let packageDefinitionWithMergedChildren; + if (_.isEmpty(packageDefinitions)) { + return; // no-op + } else if (packageDefinitions.length === 1) { + packageDefinitionWithMergedChildren = packageDefinitions[0]; + } else { + // HACK: For now, if there are two modules to display in a single section, + // we simply concat the children. This works for our limited use-case where + // we want to display types stored in two files under a single section + packageDefinitionWithMergedChildren = packageDefinitions[0]; + for (let i = 1; i < packageDefinitions.length; i++) { + packageDefinitionWithMergedChildren.children = [ + ...packageDefinitionWithMergedChildren.children, + ...packageDefinitions[i].children, + ]; + } + } + + // 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 === docsInfo.sections.types) { + entities = packageDefinitionWithMergedChildren.children; + } else { + entities = packageDefinitionWithMergedChildren.children[0].children; + const commentObj = packageDefinitionWithMergedChildren.children[0].comment; + packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; + } + + const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); + docSection.comment = packageComment; + docAgnosticFormat[sectionName] = docSection; + }); + return docAgnosticFormat; + }, + _convertEntitiesToDocSection(entities: TypeDocNode[], docsInfo: DocsInfo, 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, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + docSection.constructors.push(constructor); + break; + + case KindString.Method: + if (entity.flags.isPublic) { + isConstructor = false; + const method = typeDocUtils._convertMethod( + entity, + isConstructor, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + docSection.methods.push(method); + } + break; + + case KindString.Property: + if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) { + const property = typeDocUtils._convertProperty( + entity, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + docSection.properties.push(property); + } + break; + + case KindString.Interface: + case KindString.Function: + case KindString.Variable: + case KindString.Enumeration: + case KindString.TypeAlias: + if (docsInfo.isPublicType(entity.name)) { + const customType = typeDocUtils._convertCustomType( + entity, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + docSection.types.push(customType); + } + break; + + default: + throw utils.spawnSwitchErr('kindString', entity.kindString); + } + }); + return docSection; + }, + _convertCustomType(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): CustomType { + const typeIfExists = !_.isUndefined(entity.type) + ? typeDocUtils._convertType(entity.type, sections, sectionName, docId) + : undefined; + const isConstructor = false; + const methodIfExists = !_.isUndefined(entity.declaration) + ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) + : undefined; + const doesIndexSignatureExist = !_.isUndefined(entity.indexSignature); + const isIndexSignatureArray = _.isArray(entity.indexSignature); + // HACK: TypeDoc Versions <0.9.0 indexSignature is of type TypeDocNode[] + // Versions >0.9.0 have it as type TypeDocNode + const indexSignature = + doesIndexSignatureExist && isIndexSignatureArray + ? (entity.indexSignature as TypeDocNode[])[0] + : (entity.indexSignature as TypeDocNode); + const indexSignatureIfExists = doesIndexSignatureExist + ? typeDocUtils._convertIndexSignature(indexSignature, sections, sectionName, docId) + : 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, sections, sectionName, docId) + : 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, + sections: SectionsMap, + sectionName: string, + docId: string, + ): IndexSignature { + const key = entity.parameters[0]; + const indexSignature = { + keyName: key.name, + keyType: typeDocUtils._convertType(key.type, sections, sectionName, docId), + valueName: entity.type.name, + }; + return indexSignature; + }, + _convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: 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, sections, sectionName, docId), + source: { + fileName: source.fileName, + line: source.line, + }, + comment: commentIfExists, + }; + return property; + }, + _convertMethod( + entity: TypeDocNode, + isConstructor: boolean, + sections: SectionsMap, + sectionName: string, + docId: 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; + + // 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; + if (isConstructor || entity.name === '__type') { + callPath = ''; + // TODO: Get rid of this 0x-specific logic + } else if (docId === 'ZERO_EX_JS') { + const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.'; + callPath = + !_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx + ? `${topLevelInterface}${sectionName}.` + : topLevelInterface; + } else { + callPath = `${sectionName}.`; + } + + const parameters = _.map(signature.parameters, param => { + return typeDocUtils._convertParameter(param, sections, sectionName, docId); + }); + const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, docId); + const typeParameter = _.isUndefined(signature.typeParameter) + ? undefined + : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + + 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, + sections: SectionsMap, + sectionName: string, + docId: string, + ): TypeParameter { + const type = typeDocUtils._convertType(entity.type, sections, sectionName, docId); + const parameter = { + name: entity.name, + type, + }; + return parameter; + }, + _convertParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: 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, sections, sectionName, docId); + + const parameter = { + name: entity.name, + comment, + isOptional, + type, + }; + return parameter; + }, + _convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string, docId: string): Type { + const typeArguments = _.map(entity.typeArguments, typeArgument => { + return typeDocUtils._convertType(typeArgument, sections, sectionName, docId); + }); + const types = _.map(entity.types, t => { + return typeDocUtils._convertType(t, sections, sectionName, docId); + }); + + const isConstructor = false; + const methodIfExists = !_.isUndefined(entity.declaration) + ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) + : 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; + }, +}; diff --git a/packages/react-docs/src/ts/utils/utils.ts b/packages/react-docs/src/ts/utils/utils.ts new file mode 100644 index 000000000..8e1a80a44 --- /dev/null +++ b/packages/react-docs/src/ts/utils/utils.ts @@ -0,0 +1,10 @@ +export const utils = { + consoleLog(message: string) { + /* tslint:disable */ + console.log(message); + /* tslint:enable */ + }, + spawnSwitchErr(name: string, value: any) { + return new Error(`Unexpected switch value: ${value} encountered for ${name}`); + }, +}; |