1
1
package printer
2
2
3
3
import (
4
- "fmt"
5
4
"maps"
6
5
"slices"
7
- "strings"
8
6
"sync/atomic"
9
7
10
8
"github.com/microsoft/typescript-go/internal/ast"
@@ -16,7 +14,7 @@ import (
16
14
//
17
15
// NOTE: EmitContext is not guaranteed to be thread-safe.
18
16
type EmitContext struct {
19
- Factory * ast. NodeFactory // Required. The NodeFactory to use to create new nodes
17
+ Factory * NodeFactory // Required. The NodeFactory to use to create new nodes
20
18
autoGenerate map [* ast.MemberName ]* AutoGenerateInfo
21
19
textSource map [* ast.StringLiteralNode ]* ast.Node
22
20
original map [* ast.Node ]* ast.Node
@@ -37,11 +35,7 @@ type varScope struct {
37
35
38
36
func NewEmitContext () * EmitContext {
39
37
c := & EmitContext {}
40
- c .Factory = ast .NewNodeFactory (ast.NodeFactoryHooks {
41
- OnCreate : c .onCreate ,
42
- OnUpdate : c .onUpdate ,
43
- OnClone : c .onClone ,
44
- })
38
+ c .Factory = NewNodeFactory (c )
45
39
c .isCustomPrologue = c .isCustomPrologueWorker
46
40
c .isHoistedFunction = c .isHoistedFunctionWorker
47
41
c .isHoistedVariableStatement = c .isHoistedVariableStatementWorker
@@ -67,7 +61,7 @@ func (c *EmitContext) onClone(updated *ast.Node, original *ast.Node) {
67
61
68
62
// Creates a new NodeVisitor attached to this EmitContext
69
63
func (c * EmitContext ) NewNodeVisitor (visit func (node * ast.Node ) * ast.Node ) * ast.NodeVisitor {
70
- return ast .NewNodeVisitor (visit , c .Factory , ast.NodeVisitorHooks {
64
+ return ast .NewNodeVisitor (visit , c .Factory . AsNodeFactory () , ast.NodeVisitorHooks {
71
65
VisitParameters : c .VisitParameters ,
72
66
VisitFunctionBody : c .VisitFunctionBody ,
73
67
VisitIterationBody : c .VisitIterationBody ,
@@ -338,149 +332,10 @@ func (c *EmitContext) isHoistedVariableStatementWorker(node *ast.Statement) bool
338
332
core .Every (node .AsVariableStatement ().DeclarationList .AsVariableDeclarationList ().Declarations .Nodes , isHoistedVariable )
339
333
}
340
334
341
- // Ensures `"use strict"` is the first statement of a slice of statements.
342
- func (c * EmitContext ) EnsureUseStrict (statements []* ast.Statement ) []* ast.Statement {
343
- foundUseStrict := false
344
- for _ , statement := range statements {
345
- if ast .IsPrologueDirective (statement ) && statement .AsExpressionStatement ().Expression .Text () == "use strict" {
346
- foundUseStrict = true
347
- } else {
348
- break
349
- }
350
- }
351
- if ! foundUseStrict {
352
- useStrictPrologue := c .Factory .NewExpressionStatement (c .Factory .NewStringLiteral ("use strict" ))
353
- statements = append ([]* ast.Statement {useStrictPrologue }, statements ... )
354
- }
355
- return statements
356
- }
357
-
358
- // Splits a slice of statements into two parts: standard prologue statements and the rest of the statements
359
- func (c * EmitContext ) SplitStandardPrologue (source []* ast.Statement ) (prologue []* ast.Statement , rest []* ast.Statement ) {
360
- for i , statement := range source {
361
- if ! ast .IsPrologueDirective (statement ) {
362
- return source [:i ], source [i :]
363
- }
364
- }
365
- return nil , source
366
- }
367
-
368
- // Splits a slice of statements into two parts: custom prologue statements (e.g., with `EFCustomPrologue` set) and the rest of the statements
369
- func (c * EmitContext ) SplitCustomPrologue (source []* ast.Statement ) (prologue []* ast.Statement , rest []* ast.Statement ) {
370
- for i , statement := range source {
371
- if ast .IsPrologueDirective (statement ) || c .EmitFlags (statement )& EFCustomPrologue == 0 {
372
- return source [:i ], source [i :]
373
- }
374
- }
375
- return nil , source
376
- }
377
-
378
335
//
379
336
// Name Generation
380
337
//
381
338
382
- func (c * EmitContext ) newGeneratedIdentifier (kind GeneratedIdentifierFlags , text string , node * ast.Node , options AutoGenerateOptions ) * ast.IdentifierNode {
383
- id := AutoGenerateId (nextAutoGenerateId .Add (1 ))
384
-
385
- if len (text ) == 0 {
386
- switch {
387
- case node == nil :
388
- text = fmt .Sprintf ("(auto@%d)" , id )
389
- case ast .IsMemberName (node ):
390
- text = node .Text ()
391
- default :
392
- text = fmt .Sprintf ("(generated@%v)" , ast .GetNodeId (c .getNodeForGeneratedNameWorker (node , id )))
393
- }
394
- text = FormatGeneratedName (false /*privateName*/ , options .Prefix , text , options .Suffix )
395
- }
396
-
397
- name := c .Factory .NewIdentifier (text )
398
- autoGenerate := & AutoGenerateInfo {
399
- Id : id ,
400
- Flags : kind | (options .Flags & ^ GeneratedIdentifierFlagsKindMask ),
401
- Prefix : options .Prefix ,
402
- Suffix : options .Suffix ,
403
- Node : node ,
404
- }
405
- if c .autoGenerate == nil {
406
- c .autoGenerate = make (map [* ast.MemberName ]* AutoGenerateInfo )
407
- }
408
- c .autoGenerate [name ] = autoGenerate
409
- return name
410
- }
411
-
412
- // Allocates a new temp variable name, but does not record it in the environment. It is recommended to pass this to either
413
- // `AddVariableDeclaration` or `AddLexicalDeclaration` to ensure it is properly tracked, if you are not otherwise handling
414
- // it yourself.
415
- func (c * EmitContext ) NewTempVariable (options AutoGenerateOptions ) * ast.IdentifierNode {
416
- return c .newGeneratedIdentifier (GeneratedIdentifierFlagsAuto , "" , nil /*node*/ , options )
417
- }
418
-
419
- // Allocates a new loop variable name.
420
- func (c * EmitContext ) NewLoopVariable (options AutoGenerateOptions ) * ast.IdentifierNode {
421
- return c .newGeneratedIdentifier (GeneratedIdentifierFlagsLoop , "" , nil /*node*/ , options )
422
- }
423
-
424
- // Allocates a new unique name based on the provided text.
425
- func (c * EmitContext ) NewUniqueName (text string , options AutoGenerateOptions ) * ast.IdentifierNode {
426
- return c .newGeneratedIdentifier (GeneratedIdentifierFlagsUnique , text , nil /*node*/ , options )
427
- }
428
-
429
- // Allocates a new unique name based on the provided node.
430
- func (c * EmitContext ) NewGeneratedNameForNode (node * ast.Node , options AutoGenerateOptions ) * ast.IdentifierNode {
431
- if len (options .Prefix ) > 0 || len (options .Suffix ) > 0 {
432
- options .Flags |= GeneratedIdentifierFlagsOptimistic
433
- }
434
-
435
- return c .newGeneratedIdentifier (GeneratedIdentifierFlagsNode , "" , node , options )
436
- }
437
-
438
- func (c * EmitContext ) newGeneratedPrivateIdentifier (kind GeneratedIdentifierFlags , text string , node * ast.Node , options AutoGenerateOptions ) * ast.PrivateIdentifierNode {
439
- id := AutoGenerateId (nextAutoGenerateId .Add (1 ))
440
-
441
- if len (text ) == 0 {
442
- switch {
443
- case node == nil :
444
- text = fmt .Sprintf ("(auto@%d)" , id )
445
- case ast .IsMemberName (node ):
446
- text = node .Text ()
447
- default :
448
- text = fmt .Sprintf ("(generated@%v)" , ast .GetNodeId (c .getNodeForGeneratedNameWorker (node , id )))
449
- }
450
- text = FormatGeneratedName (true /*privateName*/ , options .Prefix , text , options .Suffix )
451
- } else if ! strings .HasPrefix (text , "#" ) {
452
- panic ("First character of private identifier must be #: " + text )
453
- }
454
-
455
- name := c .Factory .NewPrivateIdentifier (text )
456
- autoGenerate := & AutoGenerateInfo {
457
- Id : id ,
458
- Flags : kind | (options .Flags &^ GeneratedIdentifierFlagsKindMask ),
459
- Prefix : options .Prefix ,
460
- Suffix : options .Suffix ,
461
- Node : node ,
462
- }
463
- if c .autoGenerate == nil {
464
- c .autoGenerate = make (map [* ast.MemberName ]* AutoGenerateInfo )
465
- }
466
- c .autoGenerate [name ] = autoGenerate
467
- return name
468
- }
469
-
470
- // Allocates a new unique private name based on the provided text.
471
- func (c * EmitContext ) NewUniquePrivateName (text string , options AutoGenerateOptions ) * ast.PrivateIdentifierNode {
472
- return c .newGeneratedPrivateIdentifier (GeneratedIdentifierFlagsUnique , text , nil /*node*/ , options )
473
- }
474
-
475
- // Allocates a new unique private name based on the provided node.
476
- func (c * EmitContext ) NewGeneratedPrivateNameForNode (node * ast.Node , options AutoGenerateOptions ) * ast.PrivateIdentifierNode {
477
- if len (options .Prefix ) > 0 || len (options .Suffix ) > 0 {
478
- options .Flags |= GeneratedIdentifierFlagsOptimistic
479
- }
480
-
481
- return c .newGeneratedPrivateIdentifier (GeneratedIdentifierFlagsNode , "" , node , options )
482
- }
483
-
484
339
// Gets whether a given name has an associated AutoGenerateInfo entry.
485
340
func (c * EmitContext ) HasAutoGenerateInfo (node * ast.MemberName ) bool {
486
341
if node != nil {
@@ -544,87 +399,6 @@ type AutoGenerateInfo struct {
544
399
Node * ast.Node // For a GeneratedIdentifierFlagsNode, the node from which to generate an identifier
545
400
}
546
401
547
- //
548
- // Factory Utilities
549
- //
550
-
551
- // Allocates a new StringLiteral whose source text is derived from the provided node. This is often used to create a
552
- // string representation of an Identifier or NumericLiteral.
553
- func (c * EmitContext ) NewStringLiteralFromNode (textSourceNode * ast.Node ) * ast.Node {
554
- var text string
555
- if ast .IsMemberName (textSourceNode ) || ast .IsJsxNamespacedName (textSourceNode ) {
556
- text = textSourceNode .Text ()
557
- }
558
- node := c .Factory .NewStringLiteral (text )
559
- if c .textSource == nil {
560
- c .textSource = make (map [* ast.StringLiteralNode ]* ast.Node )
561
- }
562
- c .textSource [node ] = textSourceNode
563
- return node
564
- }
565
-
566
- // Allocates a new Identifier representing a reference to a helper function.
567
- func (c * EmitContext ) NewUnscopedHelperName (name string ) * ast.IdentifierNode {
568
- node := c .Factory .NewIdentifier (name )
569
- c .SetEmitFlags (node , EFHelperName )
570
- return node
571
- }
572
-
573
- // Allocates a new Call expression to the `__importDefault` helper.
574
- func (c * EmitContext ) NewImportDefaultHelper (expression * ast.Expression ) * ast.Expression {
575
- c .RequestEmitHelper (importDefaultHelper )
576
- return c .Factory .NewCallExpression (
577
- c .NewUnscopedHelperName ("__importDefault" ),
578
- nil , /*questionDotToken*/
579
- nil , /*typeArguments*/
580
- c .Factory .NewNodeList ([]* ast.Expression {expression }),
581
- ast .NodeFlagsNone ,
582
- )
583
- }
584
-
585
- // Allocates a new Call expression to the `__importStar` helper.
586
- func (c * EmitContext ) NewImportStarHelper (expression * ast.Expression ) * ast.Expression {
587
- c .RequestEmitHelper (importStarHelper )
588
- return c .Factory .NewCallExpression (
589
- c .NewUnscopedHelperName ("__importStar" ),
590
- nil , /*questionDotToken*/
591
- nil , /*typeArguments*/
592
- c .Factory .NewNodeList ([]* ast.Expression {expression }),
593
- ast .NodeFlagsNone ,
594
- )
595
- }
596
-
597
- // Allocates a new Call expression to the `__exportStar` helper.
598
- func (c * EmitContext ) NewExportStarHelper (moduleExpression * ast.Expression , exportsExpression * ast.Expression ) * ast.Expression {
599
- c .RequestEmitHelper (exportStarHelper )
600
- c .RequestEmitHelper (createBindingHelper )
601
- return c .Factory .NewCallExpression (
602
- c .NewUnscopedHelperName ("__exportStar" ),
603
- nil , /*questionDotToken*/
604
- nil , /*typeArguments*/
605
- c .Factory .NewNodeList ([]* ast.Expression {moduleExpression , exportsExpression }),
606
- ast .NodeFlagsNone ,
607
- )
608
- }
609
-
610
- // Allocates a new Call expression to the `__rewriteRelativeImportExtension` helper.
611
- func (c * EmitContext ) NewRewriteRelativeImportExtensionsHelper (firstArgument * ast.Node , preserveJsx bool ) * ast.Expression {
612
- c .RequestEmitHelper (rewriteRelativeImportExtensionsHelper )
613
- var arguments []* ast.Expression
614
- if preserveJsx {
615
- arguments = []* ast.Expression {firstArgument , c .Factory .NewToken (ast .KindTrueKeyword )}
616
- } else {
617
- arguments = []* ast.Expression {firstArgument }
618
- }
619
- return c .Factory .NewCallExpression (
620
- c .NewUnscopedHelperName ("__rewriteRelativeImportExtension" ),
621
- nil , /*questionDotToken*/
622
- nil , /*typeArguments*/
623
- c .Factory .NewNodeList (arguments ),
624
- ast .NodeFlagsNone ,
625
- )
626
- }
627
-
628
402
//
629
403
// Original Node Tracking
630
404
//
0 commit comments