Skip to content

Commit dc846b4

Browse files
arvtmcw
authored andcommitted
Handle flow tuple syntax (#511)
This fixes issues with Flow tuples `[T, V]` and Flow array types `T[]`. Fixes #510
1 parent cec558d commit dc846b4

File tree

2 files changed

+94
-46
lines changed

2 files changed

+94
-46
lines changed

lib/flow_doctrine.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ var literalTypes = {
2929
* @returns {Object} doctrine compatible type
3030
*/
3131
function flowDoctrine(type) {
32-
3332
if (type.type in namedTypes) {
3433
return {
3534
type: 'NameExpression',
@@ -41,22 +40,38 @@ function flowDoctrine(type) {
4140
return oneToOne[type.type];
4241
}
4342

44-
if (type.type === 'NullableTypeAnnotation') {
43+
switch (type.type) {
44+
case 'NullableTypeAnnotation':
4545
return {
4646
type: 'NullableType',
4747
expression: flowDoctrine(type.typeAnnotation)
4848
};
49-
}
50-
51-
if (type.type === 'UnionTypeAnnotation') {
49+
case 'UnionTypeAnnotation':
5250
return {
5351
type: 'UnionType',
5452
elements: type.types.map(flowDoctrine)
5553
};
56-
}
5754

58-
if (type.type === 'GenericTypeAnnotation') {
55+
// [number]
56+
// [string, boolean, number]
57+
case 'TupleTypeAnnotation':
58+
return {
59+
type: 'ArrayType',
60+
elements: type.types.map(flowDoctrine)
61+
};
62+
63+
// number[]
64+
case 'ArrayTypeAnnotation':
65+
return {
66+
type: 'TypeApplication',
67+
expression: {
68+
type: 'NameExpression',
69+
name: 'Array'
70+
},
71+
applications: [flowDoctrine(type.elementType)]
72+
};
5973

74+
case 'GenericTypeAnnotation':
6075
if (type.typeParameters) {
6176
return {
6277
type: 'TypeApplication',

test/lib/flow_doctrine.js

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,33 @@ function toComment(fn, filename) {
1111
})[0];
1212
}
1313

14+
function toDoctrineType(flowType) {
15+
return flowDoctrine(toComment(
16+
'/** add */function add(a: ' + flowType + ' ) { }'
17+
).context.ast.node.params[0].typeAnnotation.typeAnnotation);
18+
}
19+
1420
/* eslint-disable */
1521
test('flowDoctrine', function (t) {
1622

17-
t.deepEqual(flowDoctrine(toComment(
18-
"/** add */function add(a: number) { }"
19-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
23+
t.deepEqual(toDoctrineType('number'),
2024
{
2125
type: 'NameExpression',
2226
name: 'number'
2327
}, 'number');
2428

25-
t.deepEqual(flowDoctrine(toComment(
26-
"/** add */function add(a: string) { }"
27-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
29+
t.deepEqual(toDoctrineType('string'),
2830
{
2931
type: 'NameExpression',
3032
name: 'string'
3133
}, 'string');
3234

33-
t.deepEqual(flowDoctrine(toComment(
34-
"/** add */function add(a: any) { }"
35-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
35+
t.deepEqual(toDoctrineType('any'),
3636
{
3737
type: 'AllLiteral'
3838
}, 'all');
3939

40-
t.deepEqual(flowDoctrine(toComment(
41-
"/** add */function add(a: ?number) { }"
42-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
40+
t.deepEqual(toDoctrineType('?number'),
4341
{
4442
type: 'NullableType',
4543
expression: {
@@ -48,9 +46,7 @@ test('flowDoctrine', function (t) {
4846
}
4947
}, 'nullable');
5048

51-
t.deepEqual(flowDoctrine(toComment(
52-
"/** add */function add(a: number | string) { }"
53-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
49+
t.deepEqual(toDoctrineType('number | string'),
5450
{
5551
type: 'UnionType',
5652
elements: [
@@ -65,25 +61,19 @@ test('flowDoctrine', function (t) {
6561
]
6662
}, 'union');
6763

68-
t.deepEqual(flowDoctrine(toComment(
69-
"/** add */function add(a: Object) { }"
70-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
64+
t.deepEqual(toDoctrineType('Object'),
7165
{
7266
type: 'NameExpression',
7367
name: 'Object'
7468
}, 'object');
7569

76-
t.deepEqual(flowDoctrine(toComment(
77-
"/** add */function add(a: Array) { }"
78-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
70+
t.deepEqual(toDoctrineType('Array'),
7971
{
8072
type: 'NameExpression',
8173
name: 'Array'
8274
}, 'array');
8375

84-
t.deepEqual(flowDoctrine(toComment(
85-
"/** add */function add(a: Array<number>) { }"
86-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
76+
t.deepEqual(toDoctrineType('Array<number>'),
8777
{
8878
type: 'TypeApplication',
8979
expression: {
@@ -96,46 +86,89 @@ test('flowDoctrine', function (t) {
9686
}]
9787
}, 'Array<number>');
9888

99-
t.deepEqual(flowDoctrine(toComment(
100-
"/** add */function add(a: boolean) { }"
101-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
89+
t.deepEqual(toDoctrineType('number[]'),
90+
{
91+
type: 'TypeApplication',
92+
expression: {
93+
type: 'NameExpression',
94+
name: 'Array'
95+
},
96+
applications: [{
97+
type: 'NameExpression',
98+
name: 'number'
99+
}]
100+
}, 'number[]');
101+
102+
t.deepEqual(toDoctrineType('[]'),
103+
{
104+
type: 'ArrayType',
105+
elements: []
106+
}, '[]');
107+
108+
t.deepEqual(toDoctrineType('[number]'),
109+
{
110+
type: 'ArrayType',
111+
elements: [
112+
{
113+
type: 'NameExpression',
114+
name: 'number'
115+
}
116+
]
117+
}, '[number]');
118+
119+
t.deepEqual(toDoctrineType('[string, boolean]'),
120+
{
121+
type: 'ArrayType',
122+
elements: [
123+
{
124+
type: 'NameExpression',
125+
name: 'string'
126+
},
127+
{
128+
type: 'NameExpression',
129+
name: 'boolean'
130+
}
131+
]
132+
}, '[string, boolean]');
133+
134+
135+
t.deepEqual(toDoctrineType('boolean'),
102136
{
103137
type: 'NameExpression',
104138
name: 'boolean'
105139
}, 'boolean');
106140

107-
t.deepEqual(flowDoctrine(toComment(
108-
"/** add */function add(a: undefined) { }"
109-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
141+
t.deepEqual(toDoctrineType('undefined'),
110142
{
111143
type: 'NameExpression',
112144
name: 'undefined'
113145
}, 'undefined');
114146

115-
t.deepEqual(flowDoctrine(toComment(
116-
"/** add */function add(a: \"value\") { }"
117-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
147+
t.deepEqual(toDoctrineType('"value"'),
118148
{
119149
type: 'StringLiteral',
120150
name: 'value'
121151
}, 'StringLiteral');
122152

123-
t.deepEqual(flowDoctrine(toComment(
124-
"/** add */function add(a: 1) { }"
125-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
153+
t.deepEqual(toDoctrineType('1'),
126154
{
127155
type: 'NumberLiteral',
128156
name: '1'
129157
}, 'NumberLiteral');
130158

131-
t.deepEqual(flowDoctrine(toComment(
132-
"/** add */function add(a: true) { }"
133-
).context.ast.node.params[0].typeAnnotation.typeAnnotation),
159+
t.deepEqual(toDoctrineType('true'),
134160
{
135161
type: 'BooleanLiteral',
136162
name: true
137163
}, 'BooleanLiteral');
138164

165+
t.deepEqual(toDoctrineType('true'),
166+
{
167+
type: 'BooleanLiteral',
168+
name: true
169+
}, 'BooleanLiteral');
170+
171+
139172
t.end();
140173
});
141174
/* eslint-enable */

0 commit comments

Comments
 (0)