Skip to content

Commit

Permalink
Support rest parameters in function signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett committed Apr 28, 2019
1 parent f2193db commit 5fcc7fc
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 12 deletions.
8 changes: 7 additions & 1 deletion src/types.js
Expand Up @@ -59,12 +59,18 @@ export type FlowElementsType = FlowBaseType & {
elements: Array<FlowTypeDescriptor>,
};

export type FlowFunctionArgumentType = {
name: string,
type: FlowTypeDescriptor,
rest?: boolean,
};

export type FlowFunctionSignatureType = FlowBaseType & {
name: 'signature',
type: 'function',
raw: string,
signature: {
arguments: Array<{ name: string, type: FlowTypeDescriptor }>,
arguments: Array<FlowFunctionArgumentType>,
return: FlowTypeDescriptor,
},
};
Expand Down
16 changes: 14 additions & 2 deletions src/utils/__tests__/getFlowType-test.js
Expand Up @@ -216,7 +216,9 @@ describe('getFlowType', () => {
});

it('detects function signature type', () => {
const typePath = expression('x: (p1: number, p2: ?string) => boolean')
const typePath = expression(
'x: (p1: number, p2: ?string, ...rest: Array<string>) => boolean',
)
.get('typeAnnotation')
.get('typeAnnotation');
expect(getFlowType(typePath)).toEqual({
Expand All @@ -226,10 +228,19 @@ describe('getFlowType', () => {
arguments: [
{ name: 'p1', type: { name: 'number' } },
{ name: 'p2', type: { name: 'string', nullable: true } },
{
name: 'rest',
rest: true,
type: {
name: 'Array',
elements: [{ name: 'string' }],
raw: 'Array<string>',
},
},
],
return: { name: 'boolean' },
},
raw: '(p1: number, p2: ?string) => boolean',
raw: '(p1: number, p2: ?string, ...rest: Array<string>) => boolean',
});
});

Expand Down Expand Up @@ -265,6 +276,7 @@ describe('getFlowType', () => {
raw: 'string => boolean',
});
});

it('detects callable signature type', () => {
const typePath = expression('x: { (str: string): string, token: string }')
.get('typeAnnotation')
Expand Down
15 changes: 13 additions & 2 deletions src/utils/__tests__/getTSType-test.js
Expand Up @@ -185,7 +185,9 @@ describe('getTSType', () => {
});

it('detects function signature type', () => {
const typePath = expression('x: (p1: number, p2: string) => boolean')
const typePath = expression(
'x: (p1: number, p2: string, ...rest: Array<string>) => boolean',
)
.get('typeAnnotation')
.get('typeAnnotation');
expect(getTSType(typePath)).toEqual({
Expand All @@ -195,10 +197,19 @@ describe('getTSType', () => {
arguments: [
{ name: 'p1', type: { name: 'number' } },
{ name: 'p2', type: { name: 'string' } },
{
name: 'rest',
rest: true,
type: {
name: 'Array',
elements: [{ name: 'string' }],
raw: 'Array<string>',
},
},
],
return: { name: 'boolean' },
},
raw: '(p1: number, p2: string) => boolean',
raw: '(p1: number, p2: string, ...rest: Array<string>) => boolean',
});
});

Expand Down
18 changes: 16 additions & 2 deletions src/utils/getFlowType.js
Expand Up @@ -266,14 +266,28 @@ function handleFunctionTypeAnnotation(

path.get('params').each(param => {
const typeAnnotation = getTypeAnnotation(param);
if (!typeAnnotation) return;

type.signature.arguments.push({
name: param.node.name ? param.node.name.name : '',
type: getFlowTypeWithResolvedTypes(typeAnnotation, typeParams),
type: typeAnnotation
? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams)
: null,
});
});

if (path.node.rest) {
const rest = path.get('rest');
const typeAnnotation = getTypeAnnotation(rest);

type.signature.arguments.push({
name: rest.node.name ? rest.node.name.name : '',
type: typeAnnotation
? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams)
: null,
rest: true,
});
}

return type;
}

Expand Down
19 changes: 14 additions & 5 deletions src/utils/getTSType.js
Expand Up @@ -19,6 +19,7 @@ import type {
FlowTypeDescriptor,
FlowElementsType,
FlowFunctionSignatureType,
FlowFunctionArgumentType,
FlowObjectSignatureType,
} from '../types';

Expand All @@ -30,6 +31,7 @@ const tsTypes = {
TSAnyKeyword: 'any',
TSBooleanKeyword: 'boolean',
TSUnknownKeyword: 'unknown',
TSNeverKeyword: 'never',
TSNullKeyword: 'null',
TSUndefinedKeyword: 'undefined',
TSNumberKeyword: 'number',
Expand Down Expand Up @@ -227,12 +229,19 @@ function handleTSFunctionType(

path.get('parameters').each(param => {
const typeAnnotation = getTypeAnnotation(param);
if (!typeAnnotation) return;

type.signature.arguments.push({
const arg: FlowFunctionArgumentType = {
name: param.node.name || '',
type: getTSTypeWithResolvedTypes(typeAnnotation, typeParams),
});
type: typeAnnotation
? getTSTypeWithResolvedTypes(typeAnnotation, typeParams)
: null,
};

if (param.node.type === 'RestElement') {
arg.name = param.node.argument.name;
arg.rest = true;
}

type.signature.arguments.push(arg);
});

return type;
Expand Down

0 comments on commit 5fcc7fc

Please sign in to comment.