diff options
Diffstat (limited to 'packages/react-docs/src/utils')
-rw-r--r-- | packages/react-docs/src/utils/constants.ts | 3 | ||||
-rw-r--r-- | packages/react-docs/src/utils/doxity_utils.ts | 176 | ||||
-rw-r--r-- | packages/react-docs/src/utils/typedoc_utils.ts | 459 |
3 files changed, 265 insertions, 373 deletions
diff --git a/packages/react-docs/src/utils/constants.ts b/packages/react-docs/src/utils/constants.ts index c3c74fd11..b5b6cc00d 100644 --- a/packages/react-docs/src/utils/constants.ts +++ b/packages/react-docs/src/utils/constants.ts @@ -2,8 +2,9 @@ import { SupportedDocJson } from '../types'; export const constants = { TYPES_SECTION_NAME: 'types', + EXTERNAL_EXPORTS_SECTION_NAME: 'external exports', TYPE_TO_SYNTAX: { - [SupportedDocJson.Doxity]: 'solidity', + [SupportedDocJson.SolDoc]: 'solidity', [SupportedDocJson.TypeDoc]: 'typescript', } as { [supportedDocType: string]: string }, }; diff --git a/packages/react-docs/src/utils/doxity_utils.ts b/packages/react-docs/src/utils/doxity_utils.ts deleted file mode 100644 index 6815daa0c..000000000 --- a/packages/react-docs/src/utils/doxity_utils.ts +++ /dev/null @@ -1,176 +0,0 @@ -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: doxityUtils._convertParameters(doxityConstructor.inputs), - returnType: doxityUtils._convertType(doxityContractObj.name), - }; - constructors.push(constructor); - } - - const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( - doxityContractObj.abiDocs, - (abiDoc: DoxityAbiDoc) => { - return doxityUtils._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 = doxityUtils._convertType(outputsType); - } else { - const outputsType = `[${_.map(outputs, output => output.type).join(', ')}]`; - returnTypeIfExists = doxityUtils._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: doxityUtils._convertParameters(doxityMethod.inputs), - returnType: returnTypeIfExists, - }; - return method; - }, - ); - - const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( - doxityContractObj.abiDocs, - (abiDoc: DoxityAbiDoc) => { - return doxityUtils._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: doxityUtils._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: doxityUtils._convertEventArgs(doxityEvent.inputs), - }; - return event; - }); - - const docSection: DocSection = { - comment: doxityContractObj.title, - constructors, - methods, - properties, - types: [], - functions: [], - 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: doxityUtils._convertType(input.type), - }; - return parameter; - }); - return parameters; - }, - _convertType(typeName: string): Type { - const type = { - name: typeName, - typeDocType: TypeDocTypes.Intrinsic, - }; - return type; - }, - _isMethod(abiDoc: DoxityAbiDoc): boolean { - 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): boolean { - 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: doxityUtils._convertType(input.type), - }; - return eventArg; - }); - return eventArgs; - }, -}; diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts index a6d938e94..f74ec3e28 100644 --- a/packages/react-docs/src/utils/typedoc_utils.ts +++ b/packages/react-docs/src/utils/typedoc_utils.ts @@ -1,17 +1,14 @@ -import { errorUtils } from '@0xproject/utils'; -import * as _ from 'lodash'; - -import { DocsInfo } from '../docs_info'; import { CustomType, CustomTypeChild, DocAgnosticFormat, DocSection, + ExternalExportToLink, + ExternalTypeToLink, + GeneratedDocJson, IndexSignature, - KindString, Parameter, Property, - SectionsMap, Type, TypeDocNode, TypeDocType, @@ -19,10 +16,48 @@ import { TypeParameter, TypescriptFunction, TypescriptMethod, -} from '../types'; +} from '@0x/types'; +import { errorUtils } from '@0x/utils'; +import * as _ from 'lodash'; + +import { DocsInfo } from '../docs_info'; +import { KindString } from '../types'; + +import { constants } from './constants'; + +export class TypeDocUtils { + private readonly _typeDocNameOrder: string[]; + private readonly _externalTypeToLink: ExternalTypeToLink; + private readonly _externalExportToLink: ExternalExportToLink; + private readonly _docsInfo: DocsInfo; + private readonly _typeDocJson: TypeDocNode; + private readonly _classNames: string[]; + constructor(generatedDocJson: GeneratedDocJson, docsInfo: DocsInfo) { + this._docsInfo = docsInfo; + const exportPathOrder = generatedDocJson.metadata.exportPathOrder; + const exportPathToTypedocNames = generatedDocJson.metadata.exportPathToTypedocNames; + this._externalTypeToLink = generatedDocJson.metadata.externalTypeToLink; + this._externalExportToLink = generatedDocJson.metadata.externalExportToLink; + this._typeDocJson = generatedDocJson.typedocJson; + + this._typeDocNameOrder = _.compact( + _.flatten( + _.map(exportPathOrder, exportPath => { + return exportPathToTypedocNames[exportPath]; + }), + ), + ); -export const typeDocUtils = { - isType(entity: TypeDocNode): boolean { + this._classNames = []; + _.each(this._typeDocJson.children, file => { + _.each(file.children, child => { + if (child.kindString === KindString.Class) { + this._classNames.push(child.name); + } + }); + }); + } + public isType(entity: TypeDocNode): boolean { return ( entity.kindString === KindString.Interface || entity.kindString === KindString.Function || @@ -30,20 +65,20 @@ export const typeDocUtils = { entity.kindString === KindString.Variable || entity.kindString === KindString.Enumeration ); - }, - isMethod(entity: TypeDocNode): boolean { + } + public isMethod(entity: TypeDocNode): boolean { return entity.kindString === KindString.Method; - }, - isConstructor(entity: TypeDocNode): boolean { + } + public isConstructor(entity: TypeDocNode): boolean { return entity.kindString === KindString.Constructor; - }, - isProperty(entity: TypeDocNode): boolean { + } + public isProperty(entity: TypeDocNode): boolean { return entity.kindString === KindString.Property; - }, - isPrivateOrProtectedProperty(propertyName: string): boolean { - return _.startsWith(propertyName, '_'); - }, - getModuleDefinitionsBySectionName(versionDocObj: TypeDocNode, configModulePaths: string[]): TypeDocNode[] { + } + public isUnderscorePrefixed(name: string): boolean { + return _.startsWith(name, '_'); + } + public getModuleDefinitionsBySectionName(versionDocObj: TypeDocNode, configModulePaths: string[]): TypeDocNode[] { const moduleDefinitions: TypeDocNode[] = []; const jsonModules = versionDocObj.children; _.each(jsonModules, jsonMod => { @@ -54,66 +89,89 @@ export const typeDocUtils = { }); }); return moduleDefinitions; - }, - convertToDocAgnosticFormat(typeDocJson: TypeDocNode, docsInfo: DocsInfo): DocAgnosticFormat { - const subMenus = _.values(docsInfo.getMenu()); - const orderedSectionNames = _.flatten(subMenus); + } + public convertToDocAgnosticFormat(): DocAgnosticFormat { 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, - ]; - } - } - let entities; - let packageComment = ''; - // HACK: We assume 1 exported class per file - const classChildren = _.filter(packageDefinitionWithMergedChildren.children, (child: TypeDocNode) => { - return child.kindString === KindString.Class; - }); - if (classChildren.length > 1 && sectionName !== 'types') { - throw new Error('`react-docs` only supports projects with 1 exported class per file'); - } - const isClassExport = packageDefinitionWithMergedChildren.children[0].kindString === KindString.Class; - const isObjectLiteralExport = - packageDefinitionWithMergedChildren.children[0].kindString === KindString.ObjectLiteral; - if (isClassExport) { - entities = packageDefinitionWithMergedChildren.children[0].children; - const commentObj = packageDefinitionWithMergedChildren.children[0].comment; - packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; - } else if (isObjectLiteralExport) { - entities = packageDefinitionWithMergedChildren.children[0].children; - const commentObj = packageDefinitionWithMergedChildren.children[0].comment; - packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; - } else { - entities = packageDefinitionWithMergedChildren.children; - } + if (!_.isEmpty(this._externalExportToLink)) { + this._docsInfo.sections[constants.EXTERNAL_EXPORTS_SECTION_NAME] = constants.EXTERNAL_EXPORTS_SECTION_NAME; + this._docsInfo.markdownMenu[constants.EXTERNAL_EXPORTS_SECTION_NAME] = [ + constants.EXTERNAL_EXPORTS_SECTION_NAME, + ]; + const docSection: DocSection = { + comment: 'This package also re-exports some third-party libraries for your convenience.', + constructors: [], + methods: [], + functions: [], + properties: [], + types: [], + externalExportToLink: this._externalExportToLink, + }; + docAgnosticFormat[constants.EXTERNAL_EXPORTS_SECTION_NAME] = docSection; + } - const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); - docSection.comment = packageComment; - docAgnosticFormat[sectionName] = docSection; + const typeEntities: TypeDocNode[] = []; + _.each(this._typeDocNameOrder, typeDocName => { + const fileChildIndex = _.findIndex(this._typeDocJson.children, child => child.name === typeDocName); + const fileChild = this._typeDocJson.children[fileChildIndex]; + let sectionName: string; + _.each(fileChild.children, child => { + switch (child.kindString) { + case KindString.Class: + case KindString.ObjectLiteral: { + sectionName = child.name; + this._docsInfo.sections[sectionName] = sectionName; + this._docsInfo.markdownMenu[sectionName] = [sectionName]; + const entities = child.children; + const commentObj = child.comment; + const sectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : ''; + const isClassOrObjectLiteral = true; + const docSection = this._convertEntitiesToDocSection( + entities, + sectionName, + isClassOrObjectLiteral, + ); + docSection.comment = sectionComment; + docAgnosticFormat[sectionName] = docSection; + break; + } + case KindString.Function: { + sectionName = child.name; + this._docsInfo.sections[sectionName] = sectionName; + this._docsInfo.markdownMenu[sectionName] = [sectionName]; + const entities = [child]; + const commentObj = child.comment; + const SectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : ''; + const docSection = this._convertEntitiesToDocSection(entities, sectionName); + docSection.comment = SectionComment; + docAgnosticFormat[sectionName] = docSection; + break; + } + case KindString.Interface: + case KindString.Variable: + case KindString.Enumeration: + case KindString.TypeAlias: + typeEntities.push(child); + break; + default: + throw errorUtils.spawnSwitchErr('kindString', child.kindString); + } + }); }); + if (!_.isEmpty(typeEntities)) { + this._docsInfo.sections[constants.TYPES_SECTION_NAME] = constants.TYPES_SECTION_NAME; + this._docsInfo.markdownMenu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME]; + const docSection = this._convertEntitiesToDocSection(typeEntities, constants.TYPES_SECTION_NAME); + docAgnosticFormat[constants.TYPES_SECTION_NAME] = docSection; + } + return docAgnosticFormat; - }, - _convertEntitiesToDocSection(entities: TypeDocNode[], docsInfo: DocsInfo, sectionName: string): DocSection { + } + private _convertEntitiesToDocSection( + entities: TypeDocNode[], + sectionName: string, + isClassOrObjectLiteral: boolean = false, + ): DocSection { const docSection: DocSection = { comment: '', constructors: [], @@ -128,60 +186,44 @@ export const typeDocUtils = { switch (entity.kindString) { case KindString.Constructor: isConstructor = true; - const constructor = typeDocUtils._convertMethod( - entity, - isConstructor, - docsInfo.sections, - sectionName, - docsInfo.id, - ); + const constructor = this._convertMethod(entity, isConstructor, sectionName); docSection.constructors.push(constructor); break; case KindString.Function: if (entity.flags.isExported) { - const func = typeDocUtils._convertFunction(entity, docsInfo.sections, sectionName, docsInfo.id); - docSection.functions.push(func); + const funcName = entity.signatures[0].name; + if (!this.isUnderscorePrefixed(funcName)) { + const func = this._convertFunction(entity, sectionName, isClassOrObjectLiteral); + docSection.functions.push(func); + } } break; case KindString.Method: - if (entity.flags.isPublic) { + if (entity.flags.isPublic && !this.isUnderscorePrefixed(entity.name)) { isConstructor = false; - const method = typeDocUtils._convertMethod( - entity, - isConstructor, - docsInfo.sections, - sectionName, - docsInfo.id, - ); + const method = this._convertMethod(entity, isConstructor, sectionName); docSection.methods.push(method); } break; - case KindString.Property: - if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) { - const property = typeDocUtils._convertProperty( - entity, - docsInfo.sections, - sectionName, - docsInfo.id, - ); + case KindString.Property: { + if (!this.isUnderscorePrefixed(entity.name)) { + const property = this._convertProperty(entity, sectionName); docSection.properties.push(property); } break; + } - case KindString.Interface: case KindString.Variable: - case KindString.Enumeration: - case KindString.TypeAlias: - if (docsInfo.isPublicType(entity.name)) { - const customType = typeDocUtils._convertCustomType( - entity, - docsInfo.sections, - sectionName, - docsInfo.id, - ); + if (isClassOrObjectLiteral) { + // Render as a property + const property = this._convertProperty(entity, sectionName); + docSection.properties.push(property); + } else { + // Otherwise, render as a type + const customType = this._convertCustomType(entity, sectionName); const seenTypeNames = _.map(docSection.types, t => t.name); const isUnseen = !_.includes(seenTypeNames, customType.name); if (isUnseen) { @@ -190,6 +232,18 @@ export const typeDocUtils = { } break; + case KindString.Interface: + case KindString.Enumeration: + case KindString.TypeAlias: { + const customType = this._convertCustomType(entity, sectionName); + const seenTypeNames = _.map(docSection.types, t => t.name); + const isUnseen = !_.includes(seenTypeNames, customType.name); + if (isUnseen) { + docSection.types.push(customType); + } + break; + } + case KindString.Class: // We currently do not support more then a single class per file // except for the types section, where we ignore classes since we @@ -201,25 +255,17 @@ export const typeDocUtils = { } }); 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; + } + private _convertCustomType(entity: TypeDocNode, sectionName: string): CustomType { + const typeIfExists = !_.isUndefined(entity.type) ? this._convertType(entity.type, sectionName) : undefined; const isConstructor = false; const methodIfExists = !_.isUndefined(entity.declaration) - ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) + ? this._convertMethod(entity.declaration, isConstructor, sectionName) : 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 indexSignature = entity.indexSignature; const indexSignatureIfExists = doesIndexSignatureExist - ? typeDocUtils._convertIndexSignature(indexSignature, sections, sectionName, docId) + ? this._convertIndexSignature(indexSignature, sectionName) : undefined; const commentIfExists = !_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText) @@ -229,13 +275,13 @@ export const typeDocUtils = { const childrenIfExist = !_.isUndefined(entity.children) ? _.map(entity.children, (child: TypeDocNode) => { let childTypeIfExists = !_.isUndefined(child.type) - ? typeDocUtils._convertType(child.type, sections, sectionName, docId) + ? this._convertType(child.type, sectionName) : undefined; if (child.kindString === KindString.Method) { childTypeIfExists = { name: child.name, typeDocType: TypeDocTypes.Reflection, - method: typeDocUtils._convertMethod(child, isConstructor, sections, sectionName, docId), + method: this._convertMethod(child, isConstructor, sectionName), }; } const c: CustomTypeChild = { @@ -258,71 +304,49 @@ export const typeDocUtils = { children: childrenIfExist, }; return customType; - }, - _convertIndexSignature( - entity: TypeDocNode, - sections: SectionsMap, - sectionName: string, - docId: string, - ): IndexSignature { + } + private _convertIndexSignature(entity: TypeDocNode, sectionName: string): IndexSignature { const key = entity.parameters[0]; const indexSignature = { keyName: key.name, - keyType: typeDocUtils._convertType(key.type, sections, sectionName, docId), + keyType: this._convertType(key.type, sectionName), valueName: entity.type.name, }; return indexSignature; - }, - _convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): Property { + } + private _convertProperty(entity: TypeDocNode, sectionName: string): Property { const source = entity.sources[0]; const commentIfExists = !_.isUndefined(entity.comment) ? entity.comment.shortText : undefined; + const isConstructor = false; + const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic; + const callPath = this._getCallPath(sectionName, isStatic, isConstructor, entity.name); const property = { name: entity.name, - type: typeDocUtils._convertType(entity.type, sections, sectionName, docId), + type: this._convertType(entity.type, sectionName), source: { fileName: source.fileName, line: source.line, }, comment: commentIfExists, + callPath, }; return property; - }, - _convertMethod( - entity: TypeDocNode, - isConstructor: boolean, - sections: SectionsMap, - sectionName: string, - docId: string, - ): TypescriptMethod { + } + private _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; - // 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); + return this._convertParameter(param, sectionName); }); - const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, docId); + const returnType = this._convertType(signature.type, sectionName); const typeParameter = _.isUndefined(signature.typeParameter) ? undefined - : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + : this._convertTypeParameter(signature.typeParameter[0], sectionName); + const callPath = this._getCallPath(sectionName, isStatic, isConstructor, entity.name); const method = { isConstructor, isStatic, @@ -332,6 +356,10 @@ export const typeDocUtils = { source: { fileName: source.fileName, line: source.line, + callPath, + parameters, + returnType, + typeParameter, }, callPath, parameters, @@ -339,29 +367,49 @@ export const typeDocUtils = { typeParameter, }; return method; - }, - _convertFunction( - entity: TypeDocNode, - sections: SectionsMap, - sectionName: string, - docId: string, - ): TypescriptFunction { + } + private _getCallPath(sectionName: string, isStatic: boolean, isConstructor: boolean, entityName: string): string { + // 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 || entityName === '__type') { + callPath = ''; + } else { + const prefix = isStatic ? sectionName : this._getLowercaseSectionName(sectionName); + callPath = `${prefix}.`; + } + return callPath; + } + private _getLowercaseSectionName(sectionName: string): string { + if (_.startsWith(sectionName, 'ERC')) { + return `${sectionName.slice(0, 3).toLowerCase()}${sectionName.slice(3)}`; + } + return `${sectionName[0].toLowerCase()}${sectionName.slice(1)}`; + } + private _convertFunction(entity: TypeDocNode, sectionName: string, isObjectLiteral: boolean): TypescriptFunction { const signature = entity.signatures[0]; const source = entity.sources[0]; const hasComment = !_.isUndefined(signature.comment); const parameters = _.map(signature.parameters, param => { - return typeDocUtils._convertParameter(param, sections, sectionName, docId); + return this._convertParameter(param, sectionName); }); - const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, docId); + const returnType = this._convertType(signature.type, sectionName); const typeParameter = _.isUndefined(signature.typeParameter) ? undefined - : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + : this._convertTypeParameter(signature.typeParameter[0], sectionName); + let callPath = ''; + if (isObjectLiteral) { + const isConstructor = false; + const isStatic = false; + callPath = this._getCallPath(sectionName, isStatic, isConstructor, entity.name); + } const func = { name: signature.name, comment: hasComment ? signature.comment.shortText : undefined, returnComment: hasComment && signature.comment.returns ? signature.comment.returns : undefined, + callPath, source: { fileName: source.fileName, line: source.line, @@ -371,21 +419,19 @@ export const typeDocUtils = { typeParameter, }; return func; - }, - _convertTypeParameter( - entity: TypeDocNode, - sections: SectionsMap, - sectionName: string, - docId: string, - ): TypeParameter { - const type = typeDocUtils._convertType(entity.type, sections, sectionName, docId); + } + private _convertTypeParameter(entity: TypeDocNode, sectionName: string): TypeParameter { + let type; + if (!_.isUndefined(entity.type)) { + type = this._convertType(entity.type, sectionName); + } const parameter = { name: entity.name, type, }; return parameter; - }, - _convertParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): Parameter { + } + private _convertParameter(entity: TypeDocNode, sectionName: string): Parameter { let comment = '<No comment>'; if (entity.comment && entity.comment.shortText) { comment = entity.comment.shortText; @@ -395,7 +441,7 @@ export const typeDocUtils = { const isOptional = !_.isUndefined(entity.flags.isOptional) ? entity.flags.isOptional : false; - const type = typeDocUtils._convertType(entity.type, sections, sectionName, docId); + const type = this._convertType(entity.type, sectionName); const parameter = { name: entity.name, @@ -405,19 +451,33 @@ export const typeDocUtils = { type, }; return parameter; - }, - _convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string, docId: string): Type { + } + private _convertType(entity: TypeDocType, sectionName: string): Type { const typeArguments = _.map(entity.typeArguments, typeArgument => { - return typeDocUtils._convertType(typeArgument, sections, sectionName, docId); + return this._convertType(typeArgument, sectionName); }); const types = _.map(entity.types, t => { - return typeDocUtils._convertType(t, sections, sectionName, docId); + return this._convertType(t, sectionName); }); - const isConstructor = false; - const methodIfExists = !_.isUndefined(entity.declaration) - ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) - : undefined; + let indexSignatureIfExists; + let methodIfExists; + let tupleElementsIfExists; + const doesIndexSignatureExist = + !_.isUndefined(entity.declaration) && !_.isUndefined(entity.declaration.indexSignature); + if (doesIndexSignatureExist) { + const indexSignature = entity.declaration.indexSignature; + indexSignatureIfExists = this._convertIndexSignature(indexSignature, sectionName); + } else if (!_.isUndefined(entity.declaration)) { + const isConstructor = false; + methodIfExists = this._convertMethod(entity.declaration, isConstructor, sectionName); + } else if (entity.type === TypeDocTypes.Tuple) { + tupleElementsIfExists = _.map(entity.elements, el => { + // the following line is required due to an open tslint issue, https://github.com/palantir/tslint/issues/3540 + // tslint:disable-next-line:no-unnecessary-type-assertion + return { name: el.name, typeDocType: el.type as TypeDocTypes }; + }); + } const elementTypeIfExists = !_.isUndefined(entity.elementType) ? { @@ -426,15 +486,22 @@ export const typeDocUtils = { } : undefined; - const type = { + const type: Type = { name: entity.name, value: entity.value, + isExportedClassReference: _.includes(this._classNames, entity.name), typeDocType: entity.type, typeArguments, elementType: elementTypeIfExists, types, method: methodIfExists, + indexSignature: indexSignatureIfExists, + tupleElements: tupleElementsIfExists, }; + const externalLinkIfExists = this._externalTypeToLink[entity.name]; + if (!_.isUndefined(externalLinkIfExists)) { + type.externalLink = externalLinkIfExists; + } return type; - }, -}; + } +} // tslint:disable:max-file-line-count |