@@ -4,7 +4,7 @@ import { warn } from './logger';
4
4
import { PropTree , IPropDesc } from './PropTree' ;
5
5
import { type } from 'os' ;
6
6
7
- const rgxObjectTokenize = / ( < | > | , | \( | \) | \| ) / ;
7
+ const rgxObjectTokenize = / ( < | > | , | \( | \) | \| | \{ | \} | : ) / ;
8
8
const rgxCommaAll = / , / g;
9
9
const rgxParensAll = / \( | \) / g;
10
10
@@ -17,6 +17,7 @@ enum ENodeType {
17
17
FUNCTION , // function() has arguments for children
18
18
TUPLE , // [a,b] has types for children
19
19
TYPE , // string, X has no children
20
+ OBJECT , // {a:b, c:d} has name value pairs for children
20
21
}
21
22
class StringTreeNode {
22
23
children : StringTreeNode [ ] = [ ] ;
@@ -45,6 +46,8 @@ class StringTreeNode {
45
46
return 'TUPLE' ;
46
47
case ENodeType . TYPE :
47
48
return 'TYPE' ;
49
+ case ENodeType . OBJECT :
50
+ return 'OBJECT' ;
48
51
default :
49
52
return 'UNKNOWN'
50
53
}
@@ -86,7 +89,7 @@ function generateTree(name: string, parent: StringTreeNode | null = null) : Stri
86
89
const matchingIndex = findMatchingBracket ( parts , i + 1 , '<' , '>' ) ;
87
90
if ( matchingIndex === - 1 )
88
91
{
89
- warn ( `error` ) ;
92
+ warn ( `Unable to find matching '<', '>' brackets in ' ${ part } ', defaulting to \`any\`` , name ) ;
90
93
return anyNode ;
91
94
}
92
95
@@ -107,7 +110,7 @@ function generateTree(name: string, parent: StringTreeNode | null = null) : Stri
107
110
const matchingIndex = findMatchingBracket ( parts , i , '(' , ')' ) ;
108
111
if ( matchingIndex === - 1 )
109
112
{
110
- warn ( `error` ) ;
113
+ warn ( `Unable to find matching '(', ')' brackets in ' ${ part } ', defaulting to \`any\`` , name ) ;
111
114
return anyNode ;
112
115
}
113
116
@@ -121,12 +124,32 @@ function generateTree(name: string, parent: StringTreeNode | null = null) : Stri
121
124
continue ;
122
125
}
123
126
127
+ // Object
128
+ if ( part === '{' )
129
+ {
130
+ const matchingIndex = findMatchingBracket ( parts , i , '{' , '}' ) ;
131
+ if ( matchingIndex === - 1 )
132
+ {
133
+ warn ( `Unable to find matching '{', '}' brackets in '${ part } ', defaulting to \`any\`` , name ) ;
134
+ return anyNode ;
135
+ }
136
+
137
+ const node = new StringTreeNode ( 'Object' , ENodeType . OBJECT , parent ) ;
138
+ generateTree ( parts . slice ( i + 1 , matchingIndex ) . join ( '' ) , node ) ;
139
+ if ( ! parent )
140
+ return node ;
141
+
142
+ parent . children . push ( node ) ;
143
+ i = matchingIndex + 1 ;
144
+ continue ;
145
+ }
146
+
124
147
// TODO: Function?
125
148
126
149
// TODO: Tuples?
127
150
128
151
// skip separators, our handling below takes them into account
129
- if ( part === '|' || part === ',' )
152
+ if ( part === '|' || part === ',' || part === ':' )
130
153
{
131
154
continue ;
132
155
}
@@ -181,6 +204,37 @@ function resolveTree(node: StringTreeNode, parentTypes: ts.TypeNode[] | null = n
181
204
// resolve our type, do this for our parent (add our type to its children), or return our type if we have no parent (we are the root)
182
205
switch ( node . type )
183
206
{
207
+ case ENodeType . OBJECT :
208
+ const objectProperties : ts . TypeElement [ ] = [ ] ;
209
+
210
+ for ( var i = 0 ; i < node . children . length ; i = i + 2 )
211
+ {
212
+ let valType = childTypes [ i + 1 ] ;
213
+ if ( ! valType )
214
+ {
215
+ warn ( 'Unable to resolve object value type, this is likely due to invalid JSDoc. Defaulting to \`any\`.' , node ) ;
216
+ valType = anyTypeNode ;
217
+ }
218
+
219
+ const property = ts . createPropertySignature (
220
+ undefined , //modifiers
221
+ ts . createIdentifier ( node . children [ i ] . name ) ,
222
+ undefined , //question token
223
+ valType ,
224
+ undefined //initializer
225
+ )
226
+
227
+ objectProperties . push ( property ) ;
228
+ }
229
+
230
+ const objectNode = ts . createTypeLiteralNode ( objectProperties ) ;
231
+ ts . setEmitFlags ( objectNode , ts . EmitFlags . SingleLine ) ;
232
+
233
+ if ( ! parentTypes )
234
+ return objectNode ;
235
+
236
+ parentTypes . push ( objectNode ) ;
237
+ break ;
184
238
case ENodeType . GENERIC :
185
239
let genericNode : ts . TypeNode ;
186
240
if ( upperName === 'OBJECT' )
@@ -229,7 +283,7 @@ function resolveTree(node: StringTreeNode, parentTypes: ts.TypeNode[] | null = n
229
283
230
284
if ( ! valType )
231
285
{
232
- warn ( 'Unable to resolve array value type, defaulting to \`any\`.' , parent ) ;
286
+ warn ( 'Unable to resolve array value type, defaulting to \`any\`.' , node ) ;
233
287
valType = anyTypeNode ;
234
288
}
235
289
@@ -241,7 +295,7 @@ function resolveTree(node: StringTreeNode, parentTypes: ts.TypeNode[] | null = n
241
295
242
296
if ( ! valType )
243
297
{
244
- warn ( 'Unable to resolve class value type, defaulting to \`any\`.' , parent ) ;
298
+ warn ( 'Unable to resolve class value type, defaulting to \`any\`.' , node ) ;
245
299
valType = anyTypeNode ;
246
300
}
247
301
@@ -252,7 +306,7 @@ function resolveTree(node: StringTreeNode, parentTypes: ts.TypeNode[] | null = n
252
306
{
253
307
if ( childTypes . length === 0 )
254
308
{
255
- warn ( 'Unable to resolve generic type, defaulting to \`any\`.' , parent ) ;
309
+ warn ( 'Unable to resolve generic type, defaulting to \`any\`.' , node ) ;
256
310
childTypes . push ( anyTypeNode ) ;
257
311
}
258
312
@@ -276,7 +330,7 @@ function resolveTree(node: StringTreeNode, parentTypes: ts.TypeNode[] | null = n
276
330
case ENodeType . UNION :
277
331
if ( childTypes . length === 0 )
278
332
{
279
- warn ( 'Unable to resolve any types for union, defaulting to \`any\`.' , parent ) ;
333
+ warn ( 'Unable to resolve any types for union, defaulting to \`any\`.' , node ) ;
280
334
childTypes . push ( anyTypeNode ) ;
281
335
}
282
336
0 commit comments