Add support for displaying exported functions

This commit is contained in:
Fabio Berger
2018-03-18 18:44:52 +01:00
parent 4941ffd354
commit 794b155827
10 changed files with 139 additions and 51 deletions

View File

@@ -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.

View File

@@ -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<DocumentationProps, Documenta
const sortedMethods = _.sortBy(docSection.methods, 'name');
const methodDefs = _.map(sortedMethods, method => {
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<DocumentationProps, Documenta
<div>{methodDefs}</div>
</div>
)}
{docSection.functions.length > 0 && (
<div>
<h2 style={headerStyle}>Functions</h2>
<div>{functionDefs}</div>
</div>
)}
{!_.isUndefined(docSection.events) &&
docSection.events.length > 0 && (
<div>
@@ -318,7 +329,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
typeDefinitionByName: TypeDefinitionByName,
): React.ReactNode {
const constructorDefs = _.map(constructors, constructor => {
return this._renderMethodBlocks(constructor, sectionName, constructor.isConstructor, typeDefinitionByName);
return this._renderSignatureBlocks(constructor, sectionName, typeDefinitionByName);
});
return <div>{constructorDefs}</div>;
}
@@ -340,14 +351,13 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
</div>
);
}
private _renderMethodBlocks(
method: SolidityMethod | TypescriptMethod,
private _renderSignatureBlocks(
method: SolidityMethod | TypescriptFunction | TypescriptMethod,
sectionName: string,
isConstructor: boolean,
typeDefinitionByName: TypeDefinitionByName,
): React.ReactNode {
return (
<MethodBlock
<SignatureBlock
key={`method-${method.name}-${sectionName}`}
sectionName={sectionName}
method={method}

View File

@@ -4,7 +4,7 @@ import * as React from 'react';
import { DocsInfo } from '../docs_info';
import { CustomType, TypeDocTypes } from '../types';
import { MethodSignature } from './method_signature';
import { Signature } from './signature';
import { Type } from './type';
export interface InterfaceProps {
@@ -22,8 +22,12 @@ export function Interface(props: InterfaceProps) {
{property.type.typeDocType !== TypeDocTypes.Reflection ? (
<Type type={property.type} sectionName={props.sectionName} docsInfo={props.docsInfo} />
) : (
<MethodSignature
method={property.type.method}
<Signature
name={property.type.method.name}
returnType={property.type.method.returnType}
parameters={property.type.method.parameters}
typeParameter={property.type.method.typeParameter}
callPath={property.type.method.callPath}
sectionName={props.sectionName}
shouldHideMethodName={true}
shouldUseArrowSyntax={true}

View File

@@ -3,28 +3,33 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DocsInfo } from '../docs_info';
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
import { Parameter, Type as TypeDef, TypeDefinitionByName, TypeParameter } from '../types';
import { constants } from '../utils/constants';
import { Type } from './type';
export interface MethodSignatureProps {
method: TypescriptMethod | SolidityMethod;
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 MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => {
export const Signature: React.SFC<SignatureProps> = (props: SignatureProps) => {
const sectionName = constants.TYPES_SECTION_NAME;
const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
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
@@ -51,21 +56,21 @@ export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSi
if (!hasMoreThenTwoParams) {
paramStringArray.pop();
}
const methodName = props.shouldHideMethodName ? '' : props.method.name;
const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter)
const methodName = props.shouldHideMethodName ? '' : props.name;
const typeParameterIfExists = _.isUndefined(props.typeParameter)
? undefined
: renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
: renderTypeParameter(props.typeParameter, props.docsInfo, sectionName, props.typeDefinitionByName);
return (
<span style={{ fontSize: 15 }}>
{props.method.callPath}
{props.callPath}
{methodName}
{typeParameterIfExists}({hasMoreThenTwoParams && <br />}
{paramStringArray})
{props.method.returnType && (
{props.returnType && (
<span>
{props.shouldUseArrowSyntax ? ' => ' : ': '}{' '}
<Type
type={props.method.returnType}
type={props.returnType}
sectionName={sectionName}
typeDefinitionByName={props.typeDefinitionByName}
docsInfo={props.docsInfo}
@@ -76,15 +81,14 @@ export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSi
);
};
MethodSignature.defaultProps = defaultProps;
Signature.defaultProps = defaultProps;
function renderParameters(
method: TypescriptMethod | SolidityMethod,
parameters: Parameter[],
docsInfo: DocsInfo,
sectionName: string,
typeDefinitionByName?: TypeDefinitionByName,
) {
const parameters = method.parameters;
const params = _.map(parameters, (p: Parameter) => {
const isOptional = p.isOptional;
const type = (
@@ -106,12 +110,11 @@ function renderParameters(
}
function renderTypeParameter(
method: TypescriptMethod,
typeParameter: TypeParameter,
docsInfo: DocsInfo,
sectionName: string,
typeDefinitionByName?: TypeDefinitionByName,
) {
const typeParameter = method.typeParameter;
const typeParam = (
<span>
{`<${typeParameter.name} extends `}

View File

@@ -3,16 +3,16 @@ import * as _ from 'lodash';
import * as React from 'react';
import { DocsInfo } from '../docs_info';
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptFunction, TypescriptMethod } from '../types';
import { constants } from '../utils/constants';
import { typeDocUtils } from '../utils/typedoc_utils';
import { Comment } from './comment';
import { MethodSignature } from './method_signature';
import { Signature } from './signature';
import { SourceLink } from './source_link';
export interface MethodBlockProps {
method: SolidityMethod | TypescriptMethod;
export interface SignatureBlockProps {
method: SolidityMethod | TypescriptFunction | TypescriptMethod;
sectionName: string;
libraryVersion: string;
typeDefinitionByName: TypeDefinitionByName;
@@ -20,7 +20,7 @@ export interface MethodBlockProps {
sourceUrl: string;
}
export interface MethodBlockState {
export interface SignatureBlockState {
shouldShowAnchor: boolean;
}
@@ -35,8 +35,8 @@ const styles: Styles = {
},
};
export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockState> {
constructor(props: MethodBlockProps) {
export class SignatureBlock extends React.Component<SignatureBlockProps, SignatureBlockState> {
constructor(props: SignatureBlockProps) {
super(props);
this.state = {
shouldShowAnchor: false,
@@ -56,7 +56,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
{!method.isConstructor && (
{!(method as TypescriptMethod).isConstructor && (
<div className="flex pb2 pt2">
{(method as TypescriptMethod).isStatic && this._renderChip('Static')}
{(method as SolidityMethod).isConstant && this._renderChip('Constant')}
@@ -72,8 +72,12 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
</div>
)}
<code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}>
<MethodSignature
method={method}
<Signature
name={method.name}
returnType={method.returnType}
parameters={method.parameters}
typeParameter={(method as TypescriptMethod).typeParameter}
callPath={(method as TypescriptMethod).callPath}
sectionName={this.props.sectionName}
typeDefinitionByName={this.props.typeDefinitionByName}
docsInfo={this.props.docsInfo}

View File

@@ -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 = (
<MethodSignature
method={type.method}
<Signature
name={type.method.name}
returnType={type.method.returnType}
parameters={type.method.parameters}
typeParameter={type.method.typeParameter}
callPath={type.method.callPath}
sectionName={props.sectionName}
shouldHideMethodName={true}
shouldUseArrowSyntax={true}

View File

@@ -11,7 +11,7 @@ import { Comment } from './comment';
import { CustomEnum } from './custom_enum';
import { Enum } from './enum';
import { Interface } from './interface';
import { MethodSignature } from './method_signature';
import { Signature } from './signature';
import { Type } from './type';
export interface TypeDefinitionProps {
@@ -79,8 +79,12 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
docsInfo={this.props.docsInfo}
/>
) : (
<MethodSignature
method={customType.type.method}
<Signature
name={customType.type.method.name}
returnType={customType.type.method.returnType}
parameters={customType.type.method.parameters}
typeParameter={customType.type.method.typeParameter}
callPath={customType.type.method.callPath}
sectionName={this.props.sectionName}
shouldHideMethodName={true}
shouldUseArrowSyntax={true}

View File

@@ -7,8 +7,8 @@ export { Documentation } from './components/documentation';
export { Enum } from './components/enum';
export { EventDefinition } from './components/event_definition';
export { Interface } from './components/interface';
export { MethodBlock } from './components/method_block';
export { MethodSignature } from './components/method_signature';
export { SignatureBlock } from './components/signature_block';
export { Signature } from './components/signature';
export { SourceLink } from './components/source_link';
export { TypeDefinition } from './components/type_definition';
export { Type } from './components/type';

View File

@@ -42,6 +42,7 @@ export interface TypeDocFlags {
isStatic?: boolean;
isOptional?: boolean;
isPublic?: boolean;
isExported?: boolean;
}
export interface TypeDocGroup {
@@ -96,6 +97,7 @@ export enum KindString {
Variable = 'Variable',
Function = 'Function',
Enumeration = 'Enumeration',
Class = 'Class',
}
export interface DocAgnosticFormat {
@@ -108,6 +110,7 @@ export interface DocSection {
methods: Array<TypescriptMethod | SolidityMethod>;
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;
}

View File

@@ -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,