-
-
Notifications
You must be signed in to change notification settings - Fork 291
/
getMethodDocumentation.js
126 lines (105 loc) · 3.02 KB
/
getMethodDocumentation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import { getDocblock } from './docblock';
import getFlowType from './getFlowType';
import getTSType from './getTSType';
import getParameterName from './getParameterName';
import getPropertyName from './getPropertyName';
import getTypeAnnotation from './getTypeAnnotation';
import recast from 'recast';
import type { FlowTypeDescriptor } from '../types';
const {
types: { namedTypes: types },
} = recast;
type MethodParameter = {
name: string,
type?: ?FlowTypeDescriptor,
optional?: boolean,
};
type MethodReturn = {
type: ?FlowTypeDescriptor,
};
type MethodDocumentation = {
name: string,
docblock: ?string,
modifiers: Array<string>,
params: Array<MethodParameter>,
returns: ?MethodReturn,
};
function getMethodParamsDoc(methodPath) {
const params = [];
const functionExpression = methodPath.get('value');
// Extract param flow types.
functionExpression.get('params').each(paramPath => {
let type = null;
const typePath = getTypeAnnotation(paramPath);
if (typePath && types.Flow.check(typePath.node)) {
type = getFlowType(typePath);
if (types.GenericTypeAnnotation.check(typePath.node)) {
type.alias = typePath.node.id.name;
}
} else if (typePath) {
type = getTSType(typePath);
if (types.TSTypeReference.check(typePath.node)) {
type.alias = typePath.node.typeName.name;
}
}
const param = {
name: getParameterName(paramPath),
optional: paramPath.node.optional,
type,
};
params.push(param);
});
return params;
}
// Extract flow return type.
function getMethodReturnDoc(methodPath) {
const functionExpression = methodPath.get('value');
if (functionExpression.node.returnType) {
const returnType = getTypeAnnotation(functionExpression.get('returnType'));
if (returnType && types.Flow.check(returnType.node)) {
return { type: getFlowType(returnType) };
} else if (returnType) {
return { type: getTSType(returnType) };
}
}
return null;
}
function getMethodModifiers(methodPath) {
const modifiers = [];
if (methodPath.node.static) {
modifiers.push('static');
}
if (methodPath.node.kind === 'get' || methodPath.node.kind === 'set') {
modifiers.push(methodPath.node.kind);
}
const functionExpression = methodPath.get('value').node;
if (functionExpression.generator) {
modifiers.push('generator');
}
if (functionExpression.async) {
modifiers.push('async');
}
return modifiers;
}
export default function getMethodDocumentation(
methodPath: NodePath,
): ?MethodDocumentation {
const name = getPropertyName(methodPath);
if (!name) return null;
const docblock = getDocblock(methodPath);
return {
name,
docblock,
modifiers: getMethodModifiers(methodPath),
params: getMethodParamsDoc(methodPath),
returns: getMethodReturnDoc(methodPath),
};
}