@patternfly/ast-helpers 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1041 @@
1
+ const acorn = require('acorn')
2
+ const tt = acorn.tokTypes
3
+ function DestructuringErrors() {
4
+ this.shorthandAssign =
5
+ this.trailingComma =
6
+ this.parenthesizedAssign =
7
+ this.parenthesizedBind =
8
+ this.doubleProto =
9
+ -1
10
+ }
11
+
12
+ const tsPredefinedType = {
13
+ any: 'TSAnyKeyword',
14
+ bigint: 'TSBigIntKeyword',
15
+ boolean: 'TSBooleanKeyword',
16
+ never: 'TSNeverKeyword',
17
+ null: 'TSNullKeyword',
18
+ number: 'TSNumberKeyword',
19
+ object: 'TSObjectKeyword',
20
+ string: 'TSStringKeyword',
21
+ symbol: 'TSSymbolKeyword',
22
+ undefined: 'TSUndefinedKeyword',
23
+ unknown: 'TSUnknownKeyword',
24
+ void: 'TSVoidKeyword'
25
+ }
26
+
27
+ const tsDeclaration = {
28
+ interface: 1,
29
+ type: 2,
30
+ enum: 4,
31
+ declare: 8
32
+ }
33
+
34
+ const tsTypeOperator = {
35
+ typeof: 1,
36
+ keyof: 2,
37
+ infer: 4
38
+ }
39
+
40
+ const tsExprMarkup = {
41
+ as: 1,
42
+ '!': 2
43
+ }
44
+
45
+ module.exports = Parser => class TSParser extends Parser {
46
+ constructor(...args) {
47
+ super(...args)
48
+ // Allow 'interface'
49
+ this.reservedWords = /^(?:enum)$/
50
+ this.reservedWordsStrict = this.reservedWords
51
+ }
52
+
53
+ finishNode(node, type) {
54
+ if (type.startsWith('TS')) {
55
+ // Hack to not need acorn-walk to detect TS
56
+ this.options.sourceType = 'ts';
57
+ }
58
+ return this.finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc);
59
+ }
60
+
61
+ computeLocByOffset(offset) {
62
+ // If `locations` option is off, do nothing for saving performance.
63
+ if (this.options.locations) {
64
+ return acorn.getLineInfo(this.input, offset)
65
+ }
66
+ }
67
+
68
+ startNodeAtNode(node) {
69
+ return this.startNodeAt(node.start, this.computeLocByOffset(node.start))
70
+ }
71
+
72
+ tsPreparePreview() {
73
+ const {
74
+ pos, curLine, type, value, end, start, endLoc, startLoc, scopeStack,
75
+ lastTokStartLoc, lastTokEndLoc, lastTokEnd, lastTokStart, context,
76
+ } = this
77
+ return () => {
78
+ this.pos = pos
79
+ this.curLine = curLine
80
+ this.type = type
81
+ this.value = value
82
+ this.end = end
83
+ this.start = start
84
+ this.endLoc = endLoc
85
+ this.startLoc = startLoc
86
+ this.scopeStack = scopeStack
87
+ this.lastTokStartLoc = lastTokStartLoc
88
+ this.lastTokEndLoc = lastTokEndLoc
89
+ this.lastTokEnd = lastTokEnd
90
+ this.lastTokStart = lastTokStart
91
+ this.context = context
92
+ }
93
+ }
94
+
95
+ _isStartOfTypeParameters() {
96
+ return this.value && this.value.charCodeAt(0) === 60 // <
97
+ }
98
+
99
+ _isEndOfTypeParameters() {
100
+ return this.value && this.value.charCodeAt(0) === 62 // >
101
+ }
102
+
103
+ _hasPrecedingLineBreak() {
104
+ return acorn.lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
105
+ }
106
+
107
+ // Studied from Babel
108
+ parseExpressionStatement(node, expr) {
109
+ return expr.type === 'Identifier'
110
+ ? this._parseTSDeclaration(node, expr)
111
+ : super.parseExpressionStatement(node, expr)
112
+ }
113
+
114
+ parseBindingAtom() {
115
+ const node = super.parseBindingAtom()
116
+ if (this.eat(tt.colon)) {
117
+ node.typeAnnotation = this.parseTSTypeAnnotation(false)
118
+ node.end = node.typeAnnotation.end
119
+ if (this.options.locations) {
120
+ node.loc.end = node.typeAnnotation.loc.end
121
+ }
122
+ }
123
+ return node
124
+ }
125
+
126
+ parseMaybeDefault(startPos, startLoc, left) {
127
+ if (!left) {
128
+ left = this.parseBindingAtom()
129
+ if (this.eat(tt.question)) {
130
+ left.optional = true
131
+ }
132
+ // `parseBindingAtom` is executed,
133
+ // so we need to check type annotation again.
134
+ if (this.eat(tt.colon)) {
135
+ left.typeAnnotation = this.parseTSTypeAnnotation(false)
136
+ left.end = left.typeAnnotation.end
137
+ if (this.options.locations) {
138
+ left.loc.end = left.typeAnnotation.loc.end
139
+ }
140
+ }
141
+ }
142
+ return super.parseMaybeDefault(startPos, startLoc, left)
143
+ }
144
+
145
+ parseMaybeAssign(noIn, refDestructuringErrors, afterLeftParse) {
146
+ let node = super.parseMaybeAssign(
147
+ noIn,
148
+ refDestructuringErrors,
149
+ afterLeftParse
150
+ )
151
+ node = this._parseMaybeTSExpression(node)
152
+ return node
153
+ }
154
+
155
+ parseFunctionParams(node) {
156
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
157
+ return super.parseFunctionParams(node)
158
+ }
159
+
160
+ parseFunctionBody(node, isArrowFunction) {
161
+ // I know, return type doesn't belong to function body,
162
+ // but this will be less hacky.
163
+ if (this.eat(tt.colon)) {
164
+ node.returnType = this.parseTSTypeAnnotation(false)
165
+ }
166
+ super.parseFunctionBody(node, isArrowFunction)
167
+ }
168
+
169
+ parseParenAndDistinguishExpression(canBeArrow) {
170
+ let startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8
171
+ if (this.options.ecmaVersion >= 6) {
172
+ this.next()
173
+
174
+ let innerStartPos = this.start, innerStartLoc = this.startLoc
175
+ let exprList = [], first = true, lastIsComma = false
176
+ let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart
177
+ this.yieldPos = 0
178
+ this.awaitPos = 0
179
+ // Do not save awaitIdentPos to allow checking awaits nested in parameters
180
+ while (this.type !== tt.parenR) {
181
+ first ? first = false : this.expect(tt.comma)
182
+ if (allowTrailingComma && this.afterTrailingComma(tt.parenR, true)) {
183
+ lastIsComma = true
184
+ break
185
+ } else if (this.type === tt.ellipsis) {
186
+ spreadStart = this.start
187
+ exprList.push(this.parseParenItem(this.parseRestBinding()))
188
+ if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element")
189
+ break
190
+ } else {
191
+ exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem))
192
+ }
193
+ if (this.type === tt.colon) {
194
+ this.parseTSTypeAnnotation() // Part I added
195
+ }
196
+ }
197
+ let innerEndPos = this.start, innerEndLoc = this.startLoc
198
+ this.expect(tt.parenR)
199
+
200
+ if (canBeArrow && !this.canInsertSemicolon()) {
201
+ const branch = this._branch()
202
+ try {
203
+ if (branch.parseTSTypeAnnotation() && branch.eat(tt.arrow)) {
204
+ this.parseTSTypeAnnotation() // throw away type
205
+ }
206
+ } catch {}
207
+ if (this.eat(tt.arrow)) {
208
+ this.checkPatternErrors(refDestructuringErrors, false)
209
+ this.checkYieldAwaitInDefaultParams()
210
+ this.yieldPos = oldYieldPos
211
+ this.awaitPos = oldAwaitPos
212
+ return this.parseParenArrowList(startPos, startLoc, exprList)
213
+ }
214
+ }
215
+
216
+ if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart)
217
+ if (spreadStart) this.unexpected(spreadStart)
218
+ this.checkExpressionErrors(refDestructuringErrors, true)
219
+ this.yieldPos = oldYieldPos || this.yieldPos
220
+ this.awaitPos = oldAwaitPos || this.awaitPos
221
+
222
+ if (exprList.length > 1) {
223
+ val = this.startNodeAt(innerStartPos, innerStartLoc)
224
+ val.expressions = exprList
225
+ this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc)
226
+ } else {
227
+ val = exprList[0]
228
+ }
229
+ } else {
230
+ val = this.parseParenExpression()
231
+ }
232
+
233
+ if (this.options.preserveParens) {
234
+ let par = this.startNodeAt(startPos, startLoc)
235
+ par.expression = val
236
+ return this.finishNode(par, "ParenthesizedExpression")
237
+ } else {
238
+ return val
239
+ }
240
+ }
241
+
242
+ // Fix ambiguity between BinaryExpressions and TSCallExpressions
243
+ parseSubscript(base) {
244
+ const branch = this._branch()
245
+ if (this._isStartOfTypeParameters()) { // <
246
+ try {
247
+ // will throw if no matching >
248
+ const typeParameters = branch.parseTSTypeParameterInstantiation()
249
+ if (typeParameters && branch.eat(tt.parenL)) {
250
+ // Update parser to match branch
251
+ base.typeParameters = this.parseTSTypeParameterInstantiation()
252
+ }
253
+ } catch {}
254
+ }
255
+
256
+ return super.parseSubscript.apply(this, arguments)
257
+ }
258
+
259
+ parseExpression() {
260
+ const parenthesized = this.type === tt.parenL,
261
+ parenStart = parenthesized ? this.start : -1
262
+ let expr = super.parseExpression()
263
+
264
+ if (parenthesized) {
265
+ expr.extra = { parenthesized, parenStart }
266
+ return expr
267
+ }
268
+
269
+ expr = this._parseMaybeTSExpression(expr)
270
+ return expr
271
+ }
272
+
273
+ parseParenItem(item) {
274
+ item = super.parseParenItem(item)
275
+ item = this._parseMaybeTSExpression(item)
276
+ return item
277
+ }
278
+
279
+ // https://github.com/acornjs/acorn/blob/master/acorn/src/statement.js#L569
280
+ parseClass(node, isStatement) {
281
+ this.next()
282
+
283
+ // ecma-262 14.6 Class Definitions
284
+ // A class definition is always strict mode code.
285
+ const oldStrict = this.strict
286
+ this.strict = true
287
+
288
+ this.parseClassId(node, isStatement)
289
+ this.parseClassSuper(node)
290
+ const privateNameMap = this.enterClassBody()
291
+ const classBody = this.startNode()
292
+ let hadConstructor = false
293
+ classBody.body = []
294
+ // Lazy implementation -- discard types
295
+ this.parseMaybeTSTypeParameterInstantiation()
296
+ this.expect(tt.braceL)
297
+ while (this.type !== tt.braceR) {
298
+ const element = this.parseClassElement(node.superClass !== null)
299
+ if (element) {
300
+ classBody.body.push(element)
301
+ if (element.type === "MethodDefinition" && element.kind === "constructor") {
302
+ if (hadConstructor) this.raise(element.start, "Duplicate constructor in the same class")
303
+ hadConstructor = true
304
+ } else if (element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) {
305
+ this.raiseRecoverable(element.key.start, `Identifier '#${element.key.name}' has already been declared`)
306
+ }
307
+ }
308
+ }
309
+ this.strict = oldStrict
310
+ this.next()
311
+ node.body = this.finishNode(classBody, "ClassBody")
312
+ this.exitClassBody()
313
+ return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
314
+ }
315
+
316
+ parseTSTypeAnnotation(eatColon = true) {
317
+ eatColon && this.expect(tt.colon)
318
+ const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc)
319
+ this._parseTSTypeAnnotation(node)
320
+ return this.finishNode(node, 'TSTypeAnnotation')
321
+ }
322
+
323
+ _parseTSType() {
324
+ const node = this._parseNonConditionalType()
325
+ if (this.type === tt._extends && !this._hasPrecedingLineBreak()) {
326
+ return this.parseTSConditionalType(node)
327
+ }
328
+ return node
329
+ }
330
+
331
+ _parseTSTypeAnnotation(node) {
332
+ node.typeAnnotation = this._parseTSType()
333
+ }
334
+
335
+ _parsePrimaryType() {
336
+ let node
337
+ switch (this.type) {
338
+ case tt.name:
339
+ node = this.value in tsPredefinedType
340
+ ? this.parseTSPredefinedType()
341
+ : this.parseTSTypeReference()
342
+ break
343
+ case tt.braceL:
344
+ node = this.parseTSTypeLiteral()
345
+ break
346
+ case tt._void:
347
+ case tt._null:
348
+ node = this.parseTSPredefinedType()
349
+ break
350
+ case tt.parenL:
351
+ node = this.parseTSParenthesizedType()
352
+ break
353
+ case tt.bracketL:
354
+ node = this.parseTSTupleType()
355
+ break
356
+ case tt.num:
357
+ case tt.string:
358
+ case tt._true:
359
+ case tt._false:
360
+ node = this.parseTSLiteralType(this.type)
361
+ break
362
+ case tt._import:
363
+ node = this.parseTSImportType(false)
364
+ break
365
+ default:
366
+ return
367
+ }
368
+
369
+ if (this.type === tt.bracketL) {
370
+ node = this._parseMaybeTSArrayType(node)
371
+ }
372
+
373
+ return node
374
+ }
375
+
376
+ _parseNonConditionalType() {
377
+ let node
378
+ switch (this.type) {
379
+ case tt.name:
380
+ switch (tsTypeOperator[this.value]) {
381
+ case tsTypeOperator.infer:
382
+ node = this.parseTSInferType()
383
+ break
384
+ case tsTypeOperator.keyof:
385
+ node = this.parseTSKeyofType()
386
+ break
387
+ default:
388
+ node = this._parseTSUnionTypeOrIntersectionType()
389
+ }
390
+ break
391
+ case tt._new:
392
+ node = this.parseTSConstructorType()
393
+ break
394
+ case tt.parenL:
395
+ const recover = this.tsPreparePreview()
396
+ const isStartOfTSFunctionType = this._isStartOfTSFunctionType()
397
+ recover()
398
+ node = isStartOfTSFunctionType
399
+ ? this.parseTSFunctionType()
400
+ : this.parseTSParenthesizedType()
401
+ break
402
+ case tt.relational:
403
+ node = this._isStartOfTypeParameters()
404
+ ? this.parseTSFunctionType()
405
+ : this.unexpected()
406
+ break
407
+ case tt._typeof:
408
+ node = this.parseTSTypeofType()
409
+ break
410
+ default:
411
+ node = this._parseTSUnionTypeOrIntersectionType()
412
+ break
413
+ }
414
+ return node || this.unexpected()
415
+ }
416
+
417
+ _parseTSDeclaration(node, expr) {
418
+ const val = tsDeclaration[expr.name]
419
+ switch (val) {
420
+ case tsDeclaration.interface:
421
+ if (this.type === tt.name) {
422
+ return this.parseTSInterfaceDeclaration()
423
+ }
424
+ break
425
+ case tsDeclaration.type:
426
+ if (this.type === tt.name) {
427
+ return this.parseTSTypeAliasDeclaration()
428
+ }
429
+ break
430
+ default:
431
+ break
432
+ }
433
+ return super.parseExpressionStatement(node, expr)
434
+ }
435
+
436
+ parseTSTypeReference() {
437
+ const node = this.startNode()
438
+ let typeName = this.parseIdent()
439
+ if (this.type === tt.dot) {
440
+ typeName = this.parseTSQualifiedName(typeName)
441
+ }
442
+ node.typeName = typeName
443
+ if (this._isStartOfTypeParameters()) {
444
+ node.typeParameters = this.parseTSTypeParameterInstantiation()
445
+ }
446
+ this.finishNode(node, 'TSTypeReference')
447
+ return node
448
+ }
449
+
450
+ parseTSPredefinedType() {
451
+ const node = this.startNode()
452
+ const keyword = this.value
453
+ this.next()
454
+ this.finishNode(node, tsPredefinedType[keyword])
455
+ return node
456
+ }
457
+
458
+ parseTSLiteralType(tokType) {
459
+ const node = this.startNode()
460
+ const literal = this.parseLiteral(this.value)
461
+ if (tokType === tt._true || tokType === tt._false) {
462
+ literal.value = tokType === tt._true
463
+ }
464
+ node.literal = literal
465
+ return this.finishNode(node, 'TSLiteralType')
466
+ }
467
+
468
+ parseTSTupleType() {
469
+ const node = this.startNode()
470
+ const elementTypes = []
471
+ this.eat(tt.bracketL)
472
+ let first = true
473
+ while (!this.eat(tt.bracketR)) {
474
+ first ? (first = false) : this.expect(tt.comma)
475
+ switch (this.type) {
476
+ case tt.name:
477
+ const elem = this.parseTSTypeReference()
478
+ if (this.type === tt.question) {
479
+ elementTypes.push(this.parseTSOptionalType(elem))
480
+ } else {
481
+ elementTypes.push(elem)
482
+ }
483
+ break
484
+ case tt.ellipsis:
485
+ elementTypes.push(this.parseTSRestType())
486
+ break
487
+ case tt.bracketR:
488
+ break
489
+ default:
490
+ this.unexpected()
491
+ }
492
+ }
493
+ node.elementTypes = elementTypes
494
+ return this.finishNode(node, 'TSTupleType')
495
+ }
496
+
497
+ parseTSOptionalType(typeRef) {
498
+ const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc)
499
+ this.expect(tt.question)
500
+ node.typeAnnotation = typeRef
501
+ return this.finishNode(node, 'TSOptionalType')
502
+ }
503
+
504
+ parseTSRestType() {
505
+ const node = this.startNode()
506
+ this.expect(tt.ellipsis)
507
+ this._parseTSTypeAnnotation(node)
508
+ return this.finishNode(node, 'TSRestType')
509
+ }
510
+
511
+ _parseMaybeTSArrayType(prev) {
512
+ const node = this.startNodeAtNode(prev)
513
+ this.expect(tt.bracketL)
514
+ if (this.eat(tt.bracketR)) {
515
+ return this.parseTSArrayType(node, prev)
516
+ }
517
+ return this.parseTSIndexedAccessType(node, prev)
518
+ }
519
+
520
+ parseTSArrayType(node, elementType) {
521
+ node.elementType = elementType
522
+ return this.finishNode(node, 'TSArrayType')
523
+ }
524
+
525
+ parseTSIndexedAccessType(node, objectType) {
526
+ node.objectType = objectType
527
+ node.indexType = this._parseTSType()
528
+ this.expect(tt.bracketR)
529
+ if (this.type === tt.bracketL) {
530
+ return this._parseMaybeTSArrayType(node, objectType)
531
+ }
532
+ return this.finishNode(node, 'TSIndexedAccessType')
533
+ }
534
+
535
+ _isStartOfTSFunctionType() {
536
+ this.nextToken()
537
+ switch (this.type) {
538
+ case tt.parenR:
539
+ case tt.ellipsis:
540
+ return true
541
+ case tt.name:
542
+ case tt._this:
543
+ this.nextToken()
544
+ switch (this.type) {
545
+ case tt.colon:
546
+ case tt.comma:
547
+ case tt.question:
548
+ return true
549
+ case tt.parenR:
550
+ this.nextToken()
551
+ return this.type === tt.arrow
552
+ default:
553
+ return false
554
+ }
555
+ case tt.braceL:
556
+ case tt.bracketL:
557
+ this.type === tt.braceL
558
+ ? this.parseObj(/* isPattern */ true)
559
+ : this.parseBindingAtom()
560
+ switch (this.type) {
561
+ case tt.colon:
562
+ case tt.comma:
563
+ case tt.question:
564
+ return true
565
+ case tt.parenR:
566
+ this.nextToken()
567
+ return this.type === tt.arrow
568
+ default:
569
+ return false
570
+ }
571
+ default:
572
+ return false
573
+ }
574
+ }
575
+
576
+ parseTSFunctionType() {
577
+ const node = this.startNode()
578
+ const temp = Object.create(null)
579
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
580
+ this.parseFunctionParams(temp)
581
+ node.parameters = temp.params
582
+ this.expect(tt.arrow)
583
+ node.typeAnnotation = this.parseTSTypeAnnotation(false)
584
+ return this.finishNode(node, 'TSFunctionType')
585
+ }
586
+
587
+ parseTSParenthesizedType() {
588
+ const node = this.startNode()
589
+ this.expect(tt.parenL)
590
+ this._parseTSTypeAnnotation(node)
591
+ this.expect(tt.parenR)
592
+ if (this.eat(tt.bracketL)) {
593
+ this.expect(tt.bracketR)
594
+ }
595
+ return this.finishNode(node, 'TSParenthesizedType')
596
+ }
597
+
598
+ parseTSUnionType(first) {
599
+ const node = first
600
+ ? this.startNodeAtNode(first)
601
+ : this.startNode()
602
+ const types = []
603
+ first && types.push(first)
604
+ while (this.eat(tt.bitwiseOR)) {
605
+ types.push(this._parseTSIntersectionTypeOrPrimaryType())
606
+ }
607
+ if (types.length === 1) {
608
+ return first
609
+ }
610
+ node.types = types
611
+ return this.finishNode(node, 'TSUnionType')
612
+ }
613
+
614
+ parseTSIntersectionType(first) {
615
+ const node = first
616
+ ? this.startNodeAtNode(first)
617
+ : this.startNode()
618
+ const types = []
619
+ first && types.push(first)
620
+ while (this.eat(tt.bitwiseAND)) {
621
+ types.push(this._parsePrimaryType())
622
+ }
623
+ if (types.length === 1) {
624
+ return first
625
+ }
626
+ node.types = types
627
+ return this.finishNode(node, 'TSIntersectionType')
628
+ }
629
+
630
+ _parseTSIntersectionTypeOrPrimaryType() {
631
+ this.eat(tt.bitwiseAND)
632
+ const node = this._parsePrimaryType()
633
+ if (this.type === tt.bitwiseAND) {
634
+ return this.parseTSIntersectionType(node)
635
+ }
636
+ return node
637
+ }
638
+
639
+ _parseTSUnionTypeOrIntersectionType() {
640
+ this.eat(tt.bitwiseOR)
641
+ const node = this._parseTSIntersectionTypeOrPrimaryType()
642
+ if (this.type === tt.bitwiseOR) {
643
+ return this.parseTSUnionType(node)
644
+ }
645
+ return node
646
+ }
647
+
648
+ parseTSConditionalType(checkType) {
649
+ const node = this.startNodeAtNode(checkType)
650
+ node.checkType = checkType
651
+ this.expect(tt._extends)
652
+ node.extendsType = this._parseNonConditionalType()
653
+ this.expect(tt.question)
654
+ node.trueType = this._parseNonConditionalType()
655
+ this.expect(tt.colon)
656
+ node.falseType = this._parseNonConditionalType()
657
+ return this.finishNode(node, 'TSConditionalType')
658
+ }
659
+
660
+ parseTSInferType() {
661
+ const node = this.startNode()
662
+ this.next()
663
+ node.typeParameter = this.parseTSTypeParameter()
664
+ return this.finishNode(node, 'TSInferType')
665
+ }
666
+
667
+ parseTSKeyofType() {
668
+ const node = this.startNode()
669
+ this.next()
670
+ node.typeAnnotation = this.parseTSTypeAnnotation(false)
671
+ return this.finishNode(node, 'TSTypeOperator')
672
+ }
673
+
674
+ parseTSTypeofType() {
675
+ const node = this.startNode()
676
+ this.next()
677
+ node.exprName = this.parseIdent()
678
+ return this.finishNode(node, 'TSTypeQuery')
679
+ }
680
+
681
+ parseTSImportType(isTypeOf) {
682
+ const node = this.startNode()
683
+ node.isTypeOf = isTypeOf
684
+ this.expect(tt._import)
685
+ this.expect(tt.parenL)
686
+ node.parameter = this.parseTSLiteralType(this.type)
687
+ this.expect(tt.parenR)
688
+ if (this.eat(tt.dot)) {
689
+ let qualifier = this.parseIdent()
690
+ if (this.type === tt.dot) {
691
+ qualifier = this.parseTSQualifiedName(qualifier)
692
+ }
693
+ node.qualifier = qualifier
694
+ }
695
+ return this.finishNode(node, 'TSImportType')
696
+ }
697
+
698
+ parseTSQualifiedName(left) {
699
+ let node = this.startNodeAtNode(left)
700
+ node.left = left
701
+ this.expect(tt.dot)
702
+ node.right = this.parseIdent()
703
+ node = this.finishNode(node, 'TSQualifiedName')
704
+ if (this.type === tt.dot) {
705
+ node = this.parseTSQualifiedName(node)
706
+ }
707
+ return node
708
+ }
709
+
710
+ parseTSConstructorType() {
711
+ const node = this.startNode()
712
+ this.expect(tt._new)
713
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
714
+ this.expect(tt.parenL)
715
+ node.parameters = this.parseBindingList(
716
+ tt.parenR,
717
+ false,
718
+ this.options.ecmaVersion >= 8
719
+ )
720
+ this.expect(tt.arrow)
721
+ node.typeAnnotation = this.parseTSTypeAnnotation(false)
722
+ return this.finishNode(node, 'TSConstructorType')
723
+ }
724
+
725
+ parseTSConstructSignatureDeclaration() {
726
+ const node = this.startNode()
727
+ this.expect(tt._new)
728
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
729
+ this.expect(tt.parenL)
730
+ node.parameters = this.parseBindingList(
731
+ tt.parenR,
732
+ false,
733
+ this.options.ecmaVersion >= 8
734
+ )
735
+ if (this.eat(tt.colon)) {
736
+ node.typeAnnotation = this.parseTSTypeAnnotation(false)
737
+ }
738
+ return this.finishNode(node, 'TSConstructSignatureDeclaration')
739
+ }
740
+
741
+ parseTSTypeLiteral() {
742
+ return this._parseObjectLikeType('TSTypeLiteral', 'members')
743
+ }
744
+
745
+ parseTSTypeAliasDeclaration() {
746
+ const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc)
747
+ node.id = this.parseIdent()
748
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
749
+ this.expect(tt.eq)
750
+ this._parseTSTypeAnnotation(node)
751
+ this.semicolon()
752
+ return this.finishNode(node, 'TSTypeAliasDeclaration')
753
+ }
754
+
755
+ parseTSInterfaceDeclaration() {
756
+ const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc)
757
+ node.id = this.parseIdent()
758
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
759
+ if (this.eat(tt._extends)) {
760
+ const heritage = []
761
+ do {
762
+ heritage.push(this.parseTSExpressionWithTypeArguments())
763
+ } while (this.eat(tt.comma))
764
+ node.heritage = heritage
765
+ }
766
+ node.body = this._parseObjectLikeType('TSInterfaceBody', 'body')
767
+ this.semicolon()
768
+ return this.finishNode(node, 'TSInterfaceDeclaration')
769
+ }
770
+
771
+ parseTSExpressionWithTypeArguments() {
772
+ const node = this.startNode()
773
+ let expr = this.parseIdent()
774
+ if (this.eat(tt.dot)) {
775
+ expr = this.parseTSQualifiedName(expr)
776
+ }
777
+ node.expr = expr
778
+ if (this._isStartOfTypeParameters()) {
779
+ const typeParameters = this.parseTSTypeParameterInstantiation()
780
+ node.typeParameters = typeParameters
781
+ node.end = typeParameters.end
782
+ if (this.options.locations) {
783
+ node.loc.end = typeParameters.loc.end
784
+ }
785
+ }
786
+ return this.finishNode(node, 'TSExpressionWithTypeArguments')
787
+ }
788
+
789
+ parseTSTypeParameter() {
790
+ const node = this.startNode()
791
+ if (this.type === tt.name) {
792
+ node.name = this.value
793
+ this.next()
794
+ } else {
795
+ this.unexpected()
796
+ }
797
+ if (this.eat(tt._extends)) {
798
+ node.constraint = this._parseTSType()
799
+ }
800
+ if (this.eat(tt.eq)) {
801
+ node.default = this._parseTSType()
802
+ }
803
+ return this.finishNode(node, 'TSTypeParameter')
804
+ }
805
+
806
+ parseMaybeTSTypeParameterDeclaration() {
807
+ if (this._isStartOfTypeParameters()) {
808
+ const node = this.startNode()
809
+ const params = []
810
+ let first = true
811
+ this.next()
812
+ while (!this.eat(tt.relational)) {
813
+ first ? (first = false) : this.expect(tt.comma)
814
+ if (this._isEndOfTypeParameters()) {
815
+ break
816
+ }
817
+ params.push(this.parseTSTypeParameter())
818
+ }
819
+ node.params = params
820
+ return this.finishNode(node, 'TSTypeParameterDeclaration')
821
+ }
822
+ }
823
+
824
+ parseTSTypeParameterInstantiation() {
825
+ const node = this.startNode()
826
+ const params = []
827
+ this.next() // <
828
+ let first = true
829
+ while (this.value && !this._isEndOfTypeParameters() || this.type === tt.comma) {
830
+ first ? (first = false) : this.expect(tt.comma)
831
+
832
+ params.push(this._parseTSType())
833
+ }
834
+ if (this._isEndOfTypeParameters()) {
835
+ this.next() // > or >>
836
+ }
837
+ node.params = params
838
+ return this.finishNode(node, 'TSTypeParameterInstantiation')
839
+ }
840
+
841
+ parseMaybeTSTypeParameterInstantiation() {
842
+ if (this._isStartOfTypeParameters()) {
843
+ return this.parseTSTypeParameterInstantiation()
844
+ }
845
+ }
846
+
847
+ _parseObjectLikeType(kind, prop) {
848
+ const node = this.startNode()
849
+ this.expect(tt.braceL)
850
+ const list = []
851
+ while (!this.eat(tt.braceR)) {
852
+ switch (this.type) {
853
+ case tt.name:
854
+ const key = this.parseIdent()
855
+ switch (this.type) {
856
+ case tt.parenL:
857
+ case tt.relational:
858
+ list.push(this.parseTSMethodSignature(key))
859
+ break
860
+ case tt.colon:
861
+ case tt.semi:
862
+ case tt.comma:
863
+ case tt.braceR:
864
+ case tt.question:
865
+ list.push(this.parseTSPropertySignature(key))
866
+ break
867
+ default:
868
+ if (this._hasPrecedingLineBreak()) {
869
+ list.push(this.parseTSPropertySignature(key))
870
+ continue
871
+ }
872
+ this.unexpected()
873
+ }
874
+ break
875
+ case tt.bracketL:
876
+ const recover = this.tsPreparePreview()
877
+ this.nextToken()
878
+ if (this.type === tt.name) {
879
+ this.nextToken()
880
+ switch (this.type) {
881
+ case tt.colon:
882
+ recover()
883
+ list.push(this.parseTSIndexSignature())
884
+ break
885
+ case tt._in:
886
+ if (list.length === 0) {
887
+ recover()
888
+ return this.parseTSMappedType()
889
+ } else {
890
+ recover()
891
+ list.push(this.parseTSPropertySignature(null, true))
892
+ }
893
+ break
894
+ default:
895
+ recover()
896
+ list.push(this.parseTSPropertySignature(null, true))
897
+ }
898
+ } else {
899
+ recover()
900
+ list.push(this.parseTSPropertySignature(null, true))
901
+ }
902
+ break
903
+ case tt._new:
904
+ list.push(this.parseTSConstructSignatureDeclaration())
905
+ break
906
+ default:
907
+ this.unexpected()
908
+ }
909
+ }
910
+ node[prop] = list
911
+ return this.finishNode(node, kind)
912
+ }
913
+
914
+ parseTSMethodSignature(key) {
915
+ const node = this.startNodeAtNode(key)
916
+ node.key = key
917
+ if (this.eat(tt.question)) {
918
+ node.optional = true
919
+ }
920
+ node.typeParameters = this.parseMaybeTSTypeParameterDeclaration()
921
+ this.expect(tt.parenL)
922
+ node.parameters = this.parseBindingList(
923
+ tt.parenR,
924
+ false,
925
+ this.options.ecmaVersion >= 8
926
+ )
927
+ if (this.type === tt.colon) {
928
+ node.typeAnnotation = this.parseTSTypeAnnotation(true)
929
+ }
930
+ this.eat(tt.comma) || this.eat(tt.semi)
931
+ return this.finishNode(node, 'TSMethodSignature')
932
+ }
933
+
934
+ parseTSPropertySignature(key, computed = false) {
935
+ let node
936
+ if (computed) {
937
+ node = this.startNode()
938
+ this.expect(tt.bracketL)
939
+ node.key = this.parseExpression()
940
+ this.expect(tt.bracketR)
941
+ } else {
942
+ node = this.startNodeAtNode(key)
943
+ node.key = key
944
+ }
945
+ node.computed = computed
946
+ if (this.eat(tt.question)) {
947
+ node.optional = true
948
+ }
949
+ if (this.type === tt.colon) {
950
+ node.typeAnnotation = this.parseTSTypeAnnotation(true)
951
+ }
952
+ this.eat(tt.comma) || this.eat(tt.semi)
953
+ return this.finishNode(node, 'TSPropertySignature')
954
+ }
955
+
956
+ parseTSIndexSignature() {
957
+ const node = this.startNode()
958
+ this.expect(tt.bracketL)
959
+ const index = this.parseIdent()
960
+ index.typeAnnotation = this.parseTSTypeAnnotation(true)
961
+ index.end = index.typeAnnotation.end
962
+ if (this.options.locations) {
963
+ index.loc.end = index.typeAnnotation.loc.end
964
+ }
965
+ node.index = index
966
+ this.expect(tt.bracketR)
967
+ node.typeAnnotation = this.parseTSTypeAnnotation(true)
968
+ this.eat(tt.comma) || this.eat(tt.semi)
969
+ return this.finishNode(node, 'TSIndexSignature')
970
+ }
971
+
972
+ parseTSMappedType() {
973
+ const node = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc)
974
+ this.expect(tt.bracketL)
975
+ node.typeParameter = this._parseTSTypeParameterInTSMappedType()
976
+ this.expect(tt.bracketR)
977
+ if (this.eat(tt.question)) {
978
+ node.optional = true
979
+ }
980
+ if (this.type === tt.colon) {
981
+ node.typeAnnotation = this.parseTSTypeAnnotation(true)
982
+ }
983
+ this.semicolon()
984
+ this.expect(tt.braceR)
985
+ return this.finishNode(node, 'TSMappedType')
986
+ }
987
+
988
+ _parseTSTypeParameterInTSMappedType() {
989
+ const node = this.startNode()
990
+ if (this.type === tt.name) {
991
+ node.name = this.value
992
+ this.next()
993
+ } else {
994
+ this.unexpected()
995
+ }
996
+ this.expect(tt._in)
997
+ node.constraint = this._parseNonConditionalType()
998
+ return this.finishNode(node, 'TSTypeParameter')
999
+ }
1000
+
1001
+ _parseMaybeTSExpression(node) {
1002
+ if (
1003
+ this.type === tt.prefix && tsExprMarkup[this.value] === tsExprMarkup['!']
1004
+ ) {
1005
+ node = this.parseTSNonNullExpression(node)
1006
+ }
1007
+ if (
1008
+ this.type === tt.name && tsExprMarkup[this.value] === tsExprMarkup.as
1009
+ ) {
1010
+ node = this.parseTSAsExpression(node)
1011
+ }
1012
+ return node
1013
+ }
1014
+
1015
+ parseTSAsExpression(expression) {
1016
+ let node = expression
1017
+ while (
1018
+ this.type === tt.name && tsExprMarkup[this.value] === tsExprMarkup.as
1019
+ ) {
1020
+ const _node = this.startNodeAtNode(node)
1021
+ this.next()
1022
+ _node.expression = node
1023
+ this._parseTSTypeAnnotation(_node)
1024
+ node = this.finishNode(_node, 'TSAsExpression')
1025
+ }
1026
+ return expression
1027
+ }
1028
+
1029
+ parseTSNonNullExpression(expression) {
1030
+ let node = expression
1031
+ while (
1032
+ this.type === tt.prefix && tsExprMarkup[this.value] === tsExprMarkup['!']
1033
+ ) {
1034
+ const _node = this.startNodeAtNode(node)
1035
+ _node.expression = node
1036
+ this.next()
1037
+ node = this.finishNode(_node, 'TSNonNullExpression')
1038
+ }
1039
+ return node
1040
+ }
1041
+ }