From 794b155827868d67f1cec45bbe8c3a3e4be02597 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 18 Mar 2018 18:44:52 +0100 Subject: Add support for displaying exported functions --- packages/react-docs/CHANGELOG.md | 3 + .../react-docs/src/components/documentation.tsx | 26 ++-- packages/react-docs/src/components/interface.tsx | 10 +- .../react-docs/src/components/method_block.tsx | 150 -------------------- .../react-docs/src/components/method_signature.tsx | 128 ----------------- packages/react-docs/src/components/signature.tsx | 131 ++++++++++++++++++ .../react-docs/src/components/signature_block.tsx | 154 +++++++++++++++++++++ packages/react-docs/src/components/type.tsx | 10 +- .../react-docs/src/components/type_definition.tsx | 10 +- packages/react-docs/src/index.ts | 4 +- packages/react-docs/src/types.ts | 16 +++ packages/react-docs/src/utils/typedoc_utils.ts | 52 ++++++- 12 files changed, 391 insertions(+), 303 deletions(-) delete mode 100644 packages/react-docs/src/components/method_block.tsx delete mode 100644 packages/react-docs/src/components/method_signature.tsx create mode 100644 packages/react-docs/src/components/signature.tsx create mode 100644 packages/react-docs/src/components/signature_block.tsx diff --git a/packages/react-docs/CHANGELOG.md b/packages/react-docs/CHANGELOG.md index 7f860739f..aa1c3c210 100644 --- a/packages/react-docs/CHANGELOG.md +++ b/packages/react-docs/CHANGELOG.md @@ -5,3 +5,6 @@ * Move example out into a separate sub-package * Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452) * Handle `reflection` type rendering so that anonymous function type declarations render properly + * Rename `MethodSignature` to `Signature` and change it's props so that it can be used to render method and function signatures. + * Rename `MethodBlock` to `SignatureBlock` since it is not used to render method and function signature blocks. + * Add support for documenting exported functions. diff --git a/packages/react-docs/src/components/documentation.tsx b/packages/react-docs/src/components/documentation.tsx index b46358159..67523dcc3 100644 --- a/packages/react-docs/src/components/documentation.tsx +++ b/packages/react-docs/src/components/documentation.tsx @@ -25,6 +25,7 @@ import { SolidityMethod, SupportedDocJson, TypeDefinitionByName, + TypescriptFunction, TypescriptMethod, } from '../types'; import { constants } from '../utils/constants'; @@ -33,7 +34,7 @@ import { utils } from '../utils/utils'; import { Badge } from './badge'; import { Comment } from './comment'; import { EventDefinition } from './event_definition'; -import { MethodBlock } from './method_block'; +import { SignatureBlock } from './signature_block'; import { SourceLink } from './source_link'; import { Type } from './type'; import { TypeDefinition } from './type_definition'; @@ -216,8 +217,12 @@ export class Documentation extends React.Component { - const isConstructor = false; - return this._renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName); + return this._renderSignatureBlocks(method, sectionName, typeDefinitionByName); + }); + + const sortedFunctions = _.sortBy(docSection.functions, 'name'); + const functionDefs = _.map(sortedFunctions, func => { + return this._renderSignatureBlocks(func, sectionName, typeDefinitionByName); }); const sortedEvents = _.sortBy(docSection.events, 'name'); @@ -262,6 +267,12 @@ export class Documentation extends React.Component{methodDefs} )} + {docSection.functions.length > 0 && ( +
+

Functions

+
{functionDefs}
+
+ )} {!_.isUndefined(docSection.events) && docSection.events.length > 0 && (
@@ -318,7 +329,7 @@ export class Documentation extends React.Component { - return this._renderMethodBlocks(constructor, sectionName, constructor.isConstructor, typeDefinitionByName); + return this._renderSignatureBlocks(constructor, sectionName, typeDefinitionByName); }); return
{constructorDefs}
; } @@ -340,14 +351,13 @@ export class Documentation extends React.Component ); } - private _renderMethodBlocks( - method: SolidityMethod | TypescriptMethod, + private _renderSignatureBlocks( + method: SolidityMethod | TypescriptFunction | TypescriptMethod, sectionName: string, - isConstructor: boolean, typeDefinitionByName: TypeDefinitionByName, ): React.ReactNode { return ( - ) : ( - { - constructor(props: MethodBlockProps) { - super(props); - this.state = { - shouldShowAnchor: false, - }; - } - public render() { - const method = this.props.method; - if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) { - return null; - } - - return ( -
- {!method.isConstructor && ( -
- {(method as TypescriptMethod).isStatic && this._renderChip('Static')} - {(method as SolidityMethod).isConstant && this._renderChip('Constant')} - {(method as SolidityMethod).isPayable && this._renderChip('Payable')} -
- -
-
- )} - - - - {(method as TypescriptMethod).source && ( - - )} - {method.comment && } - {method.parameters && - !_.isEmpty(method.parameters) && ( -
-

- ARGUMENTS -

- {this._renderParameterDescriptions(method.parameters)} -
- )} - {method.returnComment && ( -
-

- RETURNS -

- -
- )} -
- ); - } - private _renderChip(text: string) { - return ( -
- {text} -
- ); - } - private _renderParameterDescriptions(parameters: Parameter[]) { - const descriptions = _.map(parameters, parameter => { - const isOptional = parameter.isOptional; - return ( -
-
-
- {parameter.name} -
-
- {isOptional && 'optional'} -
-
-
- {parameter.comment && } -
-
- ); - }); - return descriptions; - } - private _setAnchorVisibility(shouldShowAnchor: boolean) { - this.setState({ - shouldShowAnchor, - }); - } -} diff --git a/packages/react-docs/src/components/method_signature.tsx b/packages/react-docs/src/components/method_signature.tsx deleted file mode 100644 index 1400182ea..000000000 --- a/packages/react-docs/src/components/method_signature.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; - -import { DocsInfo } from '../docs_info'; -import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types'; -import { constants } from '../utils/constants'; - -import { Type } from './type'; - -export interface MethodSignatureProps { - method: TypescriptMethod | SolidityMethod; - sectionName: string; - shouldHideMethodName?: boolean; - shouldUseArrowSyntax?: boolean; - typeDefinitionByName?: TypeDefinitionByName; - docsInfo: DocsInfo; -} - -const defaultProps = { - shouldHideMethodName: false, - shouldUseArrowSyntax: false, -}; - -export const MethodSignature: React.SFC = (props: MethodSignatureProps) => { - const sectionName = constants.TYPES_SECTION_NAME; - const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName); - const paramStringArray: any[] = []; - // HACK: For now we don't put params on newlines if there are less then 2 of them. - // Ideally we would check the character length of the resulting method signature and - // if it exceeds the available space, put params on their own lines. - const hasMoreThenTwoParams = parameters.length > 2; - _.each(parameters, (param: React.ReactNode, i: number) => { - const finalParam = hasMoreThenTwoParams ? ( - - {param} - - ) : ( - param - ); - paramStringArray.push(finalParam); - const comma = hasMoreThenTwoParams ? ( - - ,
-
- ) : ( - ', ' - ); - paramStringArray.push(comma); - }); - if (!hasMoreThenTwoParams) { - paramStringArray.pop(); - } - const methodName = props.shouldHideMethodName ? '' : props.method.name; - const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter) - ? undefined - : renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName); - return ( - - {props.method.callPath} - {methodName} - {typeParameterIfExists}({hasMoreThenTwoParams &&
} - {paramStringArray}) - {props.method.returnType && ( - - {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '} - - - )} -
- ); -}; - -MethodSignature.defaultProps = defaultProps; - -function renderParameters( - method: TypescriptMethod | SolidityMethod, - docsInfo: DocsInfo, - sectionName: string, - typeDefinitionByName?: TypeDefinitionByName, -) { - const parameters = method.parameters; - const params = _.map(parameters, (p: Parameter) => { - const isOptional = p.isOptional; - const type = ( - - ); - return ( - - {p.name} - {isOptional && '?'}: {type} - - ); - }); - return params; -} - -function renderTypeParameter( - method: TypescriptMethod, - docsInfo: DocsInfo, - sectionName: string, - typeDefinitionByName?: TypeDefinitionByName, -) { - const typeParameter = method.typeParameter; - const typeParam = ( - - {`<${typeParameter.name} extends `} - - {`>`} - - ); - return typeParam; -} diff --git a/packages/react-docs/src/components/signature.tsx b/packages/react-docs/src/components/signature.tsx new file mode 100644 index 000000000..83fb1e246 --- /dev/null +++ b/packages/react-docs/src/components/signature.tsx @@ -0,0 +1,131 @@ +import * as _ from 'lodash'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; + +import { DocsInfo } from '../docs_info'; +import { Parameter, Type as TypeDef, TypeDefinitionByName, TypeParameter } from '../types'; +import { constants } from '../utils/constants'; + +import { Type } from './type'; + +export interface SignatureProps { + name: string; + returnType: TypeDef; + parameters: Parameter[]; + sectionName: string; + shouldHideMethodName?: boolean; + shouldUseArrowSyntax?: boolean; + typeDefinitionByName?: TypeDefinitionByName; + typeParameter?: TypeParameter; + callPath?: string; + docsInfo: DocsInfo; +} + +const defaultProps = { + shouldHideMethodName: false, + shouldUseArrowSyntax: false, + callPath: '', +}; + +export const Signature: React.SFC = (props: SignatureProps) => { + const sectionName = constants.TYPES_SECTION_NAME; + const parameters = renderParameters(props.parameters, props.docsInfo, sectionName, props.typeDefinitionByName); + const paramStringArray: any[] = []; + // HACK: For now we don't put params on newlines if there are less then 2 of them. + // Ideally we would check the character length of the resulting method signature and + // if it exceeds the available space, put params on their own lines. + const hasMoreThenTwoParams = parameters.length > 2; + _.each(parameters, (param: React.ReactNode, i: number) => { + const finalParam = hasMoreThenTwoParams ? ( + + {param} + + ) : ( + param + ); + paramStringArray.push(finalParam); + const comma = hasMoreThenTwoParams ? ( + + ,
+
+ ) : ( + ', ' + ); + paramStringArray.push(comma); + }); + if (!hasMoreThenTwoParams) { + paramStringArray.pop(); + } + const methodName = props.shouldHideMethodName ? '' : props.name; + const typeParameterIfExists = _.isUndefined(props.typeParameter) + ? undefined + : renderTypeParameter(props.typeParameter, props.docsInfo, sectionName, props.typeDefinitionByName); + return ( + + {props.callPath} + {methodName} + {typeParameterIfExists}({hasMoreThenTwoParams &&
} + {paramStringArray}) + {props.returnType && ( + + {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '} + + + )} +
+ ); +}; + +Signature.defaultProps = defaultProps; + +function renderParameters( + parameters: Parameter[], + docsInfo: DocsInfo, + sectionName: string, + typeDefinitionByName?: TypeDefinitionByName, +) { + const params = _.map(parameters, (p: Parameter) => { + const isOptional = p.isOptional; + const type = ( + + ); + return ( + + {p.name} + {isOptional && '?'}: {type} + + ); + }); + return params; +} + +function renderTypeParameter( + typeParameter: TypeParameter, + docsInfo: DocsInfo, + sectionName: string, + typeDefinitionByName?: TypeDefinitionByName, +) { + const typeParam = ( + + {`<${typeParameter.name} extends `} + + {`>`} + + ); + return typeParam; +} diff --git a/packages/react-docs/src/components/signature_block.tsx b/packages/react-docs/src/components/signature_block.tsx new file mode 100644 index 000000000..6475d3995 --- /dev/null +++ b/packages/react-docs/src/components/signature_block.tsx @@ -0,0 +1,154 @@ +import { AnchorTitle, colors, HeaderSizes, Styles } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; + +import { DocsInfo } from '../docs_info'; +import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptFunction, TypescriptMethod } from '../types'; +import { constants } from '../utils/constants'; +import { typeDocUtils } from '../utils/typedoc_utils'; + +import { Comment } from './comment'; +import { Signature } from './signature'; +import { SourceLink } from './source_link'; + +export interface SignatureBlockProps { + method: SolidityMethod | TypescriptFunction | TypescriptMethod; + sectionName: string; + libraryVersion: string; + typeDefinitionByName: TypeDefinitionByName; + docsInfo: DocsInfo; + sourceUrl: string; +} + +export interface SignatureBlockState { + shouldShowAnchor: boolean; +} + +const styles: Styles = { + chip: { + fontSize: 13, + backgroundColor: colors.lightBlueA700, + color: colors.white, + height: 11, + borderRadius: 14, + lineHeight: 0.9, + }, +}; + +export class SignatureBlock extends React.Component { + constructor(props: SignatureBlockProps) { + super(props); + this.state = { + shouldShowAnchor: false, + }; + } + public render() { + const method = this.props.method; + if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) { + return null; + } + + return ( +
+ {!(method as TypescriptMethod).isConstructor && ( +
+ {(method as TypescriptMethod).isStatic && this._renderChip('Static')} + {(method as SolidityMethod).isConstant && this._renderChip('Constant')} + {(method as SolidityMethod).isPayable && this._renderChip('Payable')} +
+ +
+
+ )} + + + + {(method as TypescriptMethod).source && ( + + )} + {method.comment && } + {method.parameters && + !_.isEmpty(method.parameters) && ( +
+

+ ARGUMENTS +

+ {this._renderParameterDescriptions(method.parameters)} +
+ )} + {method.returnComment && ( +
+

+ RETURNS +

+ +
+ )} +
+ ); + } + private _renderChip(text: string) { + return ( +
+ {text} +
+ ); + } + private _renderParameterDescriptions(parameters: Parameter[]) { + const descriptions = _.map(parameters, parameter => { + const isOptional = parameter.isOptional; + return ( +
+
+
+ {parameter.name} +
+
+ {isOptional && 'optional'} +
+
+
+ {parameter.comment && } +
+
+ ); + }); + return descriptions; + } + private _setAnchorVisibility(shouldShowAnchor: boolean) { + this.setState({ + shouldShowAnchor, + }); + } +} diff --git a/packages/react-docs/src/components/type.tsx b/packages/react-docs/src/components/type.tsx index b253f0397..fd4562ce3 100644 --- a/packages/react-docs/src/components/type.tsx +++ b/packages/react-docs/src/components/type.tsx @@ -9,7 +9,7 @@ import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '../types'; import { constants } from '../utils/constants'; import { utils } from '../utils/utils'; -import { MethodSignature } from './method_signature'; +import { Signature } from './signature'; import { TypeDefinition } from './type_definition'; const typeToSection: { [typeName: string]: string } = { @@ -104,8 +104,12 @@ export function Type(props: TypeProps): any { case TypeDocTypes.Reflection: typeName = ( - ) : ( - ; properties: Property[]; types: CustomType[]; + functions?: TypescriptFunction[]; events?: Event[]; } @@ -117,6 +120,11 @@ export interface TypescriptMethod extends BaseMethod { typeParameter?: TypeParameter; } +export interface TypescriptFunction extends BaseFunction { + source?: Source; + typeParameter?: TypeParameter; +} + export interface SolidityMethod extends BaseMethod { isConstant?: boolean; isPayable?: boolean; @@ -205,6 +213,14 @@ export interface BaseMethod { comment?: string; } +export interface BaseFunction { + name: string; + returnComment?: string | undefined; + parameters: Parameter[]; + returnType: Type; + comment?: string; +} + export interface TypeDefinitionByName { [typeName: string]: CustomType; } diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts index e4cea1e40..4c7617234 100644 --- a/packages/react-docs/src/utils/typedoc_utils.ts +++ b/packages/react-docs/src/utils/typedoc_utils.ts @@ -15,6 +15,7 @@ import { TypeDocNode, TypeDocType, TypeParameter, + TypescriptFunction, TypescriptMethod, } from '../types'; import { utils } from '../utils/utils'; @@ -81,17 +82,16 @@ export const typeDocUtils = { } } - // 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 { + // HACK: We assume 1 exported class per file + const isClassExport = packageDefinitionWithMergedChildren.children[0].kindString === KindString.Class; + if (isClassExport) { entities = packageDefinitionWithMergedChildren.children[0].children; const commentObj = packageDefinitionWithMergedChildren.children[0].comment; packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; + } else { + entities = packageDefinitionWithMergedChildren.children; } const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); @@ -105,6 +105,7 @@ export const typeDocUtils = { comment: '', constructors: [], methods: [], + functions: [], properties: [], types: [], }; @@ -124,6 +125,13 @@ export const typeDocUtils = { 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); + } + break; + case KindString.Method: if (entity.flags.isPublic) { isConstructor = false; @@ -303,6 +311,38 @@ export const typeDocUtils = { }; return method; }, + _convertFunction( + entity: TypeDocNode, + sections: SectionsMap, + sectionName: string, + docId: string, + ): 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); + }); + const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, docId); + const typeParameter = _.isUndefined(signature.typeParameter) + ? undefined + : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + + const func = { + 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, + }, + parameters, + returnType, + typeParameter, + }; + return func; + }, _convertTypeParameter( entity: TypeDocNode, sections: SectionsMap, -- cgit v1.2.3