diff --git a/internal/compiler/emitter.go b/internal/compiler/emitter.go index a01185fea7..9dff66ebe4 100644 --- a/internal/compiler/emitter.go +++ b/internal/compiler/emitter.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/diagnostics" "github.com/microsoft/typescript-go/internal/outputpaths" @@ -12,6 +13,10 @@ import ( "github.com/microsoft/typescript-go/internal/stringutil" "github.com/microsoft/typescript-go/internal/transformers" "github.com/microsoft/typescript-go/internal/transformers/declarations" + "github.com/microsoft/typescript-go/internal/transformers/estransforms" + "github.com/microsoft/typescript-go/internal/transformers/jsxtransforms" + "github.com/microsoft/typescript-go/internal/transformers/moduletransforms" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" "github.com/microsoft/typescript-go/internal/tspath" ) @@ -49,6 +54,73 @@ func (e *emitter) getDeclarationTransformers(emitContext *printer.EmitContext, s return []*declarations.DeclarationTransformer{transform} } +func getModuleTransformer(emitContext *printer.EmitContext, options *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *transformers.Transformer { + switch options.GetEmitModuleKind() { + case core.ModuleKindPreserve: + // `ESModuleTransformer` contains logic for preserving CJS input syntax in `--module preserve` + return moduletransforms.NewESModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) + + case core.ModuleKindESNext, + core.ModuleKindES2022, + core.ModuleKindES2020, + core.ModuleKindES2015, + core.ModuleKindNode18, + core.ModuleKindNode16, + core.ModuleKindNodeNext, + core.ModuleKindCommonJS: + return moduletransforms.NewImpliedModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) + + default: + return moduletransforms.NewCommonJSModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) + } +} + +func getScriptTransformers(emitContext *printer.EmitContext, host printer.EmitHost, sourceFile *ast.SourceFile) []*transformers.Transformer { + var tx []*transformers.Transformer + options := host.Options() + + // JS files don't use reference calculations as they don't do import elision, no need to calculate it + importElisionEnabled := !options.VerbatimModuleSyntax.IsTrue() && !ast.IsInJSFile(sourceFile.AsNode()) + + var emitResolver printer.EmitResolver + var referenceResolver binder.ReferenceResolver + if importElisionEnabled || options.GetJSXTransformEnabled() { + emitResolver = host.GetEmitResolver(sourceFile, false /*skipDiagnostics*/) // !!! conditionally skip diagnostics + emitResolver.MarkLinkedReferencesRecursively(sourceFile) + referenceResolver = emitResolver + } else { + referenceResolver = binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{}) + } + + // transform TypeScript syntax + { + // erase types + tx = append(tx, tstransforms.NewTypeEraserTransformer(emitContext, options)) + + // elide imports + if importElisionEnabled { + tx = append(tx, tstransforms.NewImportElisionTransformer(emitContext, options, emitResolver)) + } + + // transform `enum`, `namespace`, and parameter properties + tx = append(tx, tstransforms.NewRuntimeSyntaxTransformer(emitContext, options, referenceResolver)) + } + + // !!! transform legacy decorator syntax + if options.GetJSXTransformEnabled() { + tx = append(tx, jsxtransforms.NewJSXTransformer(emitContext, options, emitResolver)) + } + + downleveler := estransforms.GetESTransformer(options, emitContext) + if downleveler != nil { + tx = append(tx, downleveler) + } + + // transform module syntax + tx = append(tx, getModuleTransformer(emitContext, options, referenceResolver, host.GetEmitModuleFormatOfFile)) + return tx +} + func (e *emitter) emitJSFile(sourceFile *ast.SourceFile, jsFilePath string, sourceMapFilePath string) { options := e.host.Options() @@ -61,7 +133,7 @@ func (e *emitter) emitJSFile(sourceFile *ast.SourceFile, jsFilePath string, sour } emitContext := printer.NewEmitContext() - for _, transformer := range transformers.GetScriptTransformers(emitContext, e.host, sourceFile) { + for _, transformer := range getScriptTransformers(emitContext, e.host, sourceFile) { sourceFile = transformer.TransformSourceFile(sourceFile) } diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index 90fb6e2f56..58f18f2893 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -8,7 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" - "github.com/microsoft/typescript-go/internal/transformers" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" ) func TestEmit(t *testing.T) { @@ -2504,7 +2504,7 @@ func TestPartiallyEmittedExpression(t *testing.T) { .expression;`, false /*jsx*/) emitContext := printer.NewEmitContext() - file = transformers.NewTypeEraserTransformer(emitContext, compilerOptions).TransformSourceFile(file) + file = tstransforms.NewTypeEraserTransformer(emitContext, compilerOptions).TransformSourceFile(file) emittestutil.CheckEmit(t, emitContext, file.AsSourceFile(), `return container.parent .left .expression diff --git a/internal/transformers/chain.go b/internal/transformers/chain.go new file mode 100644 index 0000000000..dcf7f3567a --- /dev/null +++ b/internal/transformers/chain.go @@ -0,0 +1,44 @@ +package transformers + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" +) + +type chainedTransformer struct { + Transformer + components []*Transformer +} + +func (ch *chainedTransformer) visit(node *ast.Node) *ast.Node { + if node.Kind != ast.KindSourceFile { + panic("Chained transform passed non-sourcefile initial node") + } + result := node.AsSourceFile() + for _, t := range ch.components { + result = t.TransformSourceFile(result) + } + return result.AsNode() +} + +type TransformerFactory = func(emitContext *printer.EmitContext) *Transformer + +// Chains transforms in left-to-right order, running them one at a time in order (as opposed to interleaved at each node) +// - the resulting combined transform only operates on SourceFile nodes +func Chain(transforms ...TransformerFactory) TransformerFactory { + if len(transforms) < 2 { + if len(transforms) == 0 { + panic("Expected some number of transforms to chain, but got none") + } + return transforms[0] + } + return func(emitContext *printer.EmitContext) *Transformer { + constructed := make([]*Transformer, 0, len(transforms)) + for _, t := range transforms { + // TODO: flatten nested chains? + constructed = append(constructed, t(emitContext)) + } + ch := &chainedTransformer{components: constructed} + return ch.NewTransformer(ch.visit, emitContext) + } +} diff --git a/internal/transformers/estransforms/async.go b/internal/transformers/estransforms/async.go new file mode 100644 index 0000000000..15024fbcfe --- /dev/null +++ b/internal/transformers/estransforms/async.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type asyncTransformer struct { + transformers.Transformer +} + +func (ch *asyncTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newAsyncTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &asyncTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/classfields.go b/internal/transformers/estransforms/classfields.go new file mode 100644 index 0000000000..c4e43e15f9 --- /dev/null +++ b/internal/transformers/estransforms/classfields.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type classFieldsTransformer struct { + transformers.Transformer +} + +func (ch *classFieldsTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newClassFieldsTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &classFieldsTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/classstatic.go b/internal/transformers/estransforms/classstatic.go new file mode 100644 index 0000000000..d880de75fe --- /dev/null +++ b/internal/transformers/estransforms/classstatic.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type classStaticBlockTransformer struct { + transformers.Transformer +} + +func (ch *classStaticBlockTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newClassStaticBlockTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &classStaticBlockTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/classthis.go b/internal/transformers/estransforms/classthis.go similarity index 98% rename from internal/transformers/classthis.go rename to internal/transformers/estransforms/classthis.go index c9d31956b4..063201e4b6 100644 --- a/internal/transformers/classthis.go +++ b/internal/transformers/estransforms/classthis.go @@ -1,4 +1,4 @@ -package transformers +package estransforms import ( "github.com/microsoft/typescript-go/internal/ast" diff --git a/internal/transformers/estransforms/definitions.go b/internal/transformers/estransforms/definitions.go new file mode 100644 index 0000000000..d4c025285a --- /dev/null +++ b/internal/transformers/estransforms/definitions.go @@ -0,0 +1,46 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +// !!! TODO: This fixed layering scheme assumes you can't swap out the es decorator transform for the legacy one, +// or the proper es class field transform for the legacy one +var ( + NewESNextTransformer = transformers.Chain(newESDecoratorTransformer, newUsingDeclarationTransformer) + // 2025: only module system syntax (import attributes, json modules), untransformed regex modifiers + // 2024: no new downlevel syntax + // 2023: no new downlevel syntax + NewES2022Transformer = transformers.Chain(NewESNextTransformer, newClassStaticBlockTransformer, newClassFieldsTransformer) // !!! top level await? not transformed, just errored on at lower targets - also more of a module system feature anyway + NewES2021Transformer = transformers.Chain(NewES2022Transformer, newLogicalAssignmentTransformer) // !!! numeric seperators? always elided by printer? + NewES2020Transformer = transformers.Chain(NewES2021Transformer, newNullishCoalescingTransformer, newOptionalChainTransformer) // also dynamic import - module system feature + NewES2019Transformer = transformers.Chain(NewES2020Transformer, newOptionalCatchTransformer) + NewES2018Transformer = transformers.Chain(NewES2019Transformer, newObjectRestSpreadTransformer, newforawaitTransformer) + NewES2017Transformer = transformers.Chain(NewES2018Transformer, newAsyncTransformer) + NewES2016Transformer = transformers.Chain(NewES2017Transformer, newExponentiationTransformer) +) + +func GetESTransformer(options *core.CompilerOptions, emitContext *printer.EmitContext) *transformers.Transformer { + switch options.GetEmitScriptTarget() { + case core.ScriptTargetESNext: + return nil // no transforms needed + case /*core.ScriptTargetES2025,*/ core.ScriptTargetES2024, core.ScriptTargetES2023, core.ScriptTargetES2022: + return NewESNextTransformer(emitContext) + case core.ScriptTargetES2021: + return NewES2022Transformer(emitContext) + case core.ScriptTargetES2020: + return NewES2021Transformer(emitContext) + case core.ScriptTargetES2019: + return NewES2020Transformer(emitContext) + case core.ScriptTargetES2018: + return NewES2019Transformer(emitContext) + case core.ScriptTargetES2017: + return NewES2018Transformer(emitContext) + case core.ScriptTargetES2016: + return NewES2017Transformer(emitContext) + default: // other, older, option, transform maximally + return NewES2016Transformer(emitContext) + } +} diff --git a/internal/transformers/estransforms/esdecorator.go b/internal/transformers/estransforms/esdecorator.go new file mode 100644 index 0000000000..8a71913929 --- /dev/null +++ b/internal/transformers/estransforms/esdecorator.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type esDecoratorTransformer struct { + transformers.Transformer +} + +func (ch *esDecoratorTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newESDecoratorTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &esDecoratorTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/exponentiation.go b/internal/transformers/estransforms/exponentiation.go new file mode 100644 index 0000000000..ffcc297fbd --- /dev/null +++ b/internal/transformers/estransforms/exponentiation.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type exponentiationTransformer struct { + transformers.Transformer +} + +func (ch *exponentiationTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newExponentiationTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &exponentiationTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/forawait.go b/internal/transformers/estransforms/forawait.go new file mode 100644 index 0000000000..8f6e9d5fb0 --- /dev/null +++ b/internal/transformers/estransforms/forawait.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type forawaitTransformer struct { + transformers.Transformer +} + +func (ch *forawaitTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newforawaitTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &forawaitTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/logicalassignment.go b/internal/transformers/estransforms/logicalassignment.go new file mode 100644 index 0000000000..ba547abf5d --- /dev/null +++ b/internal/transformers/estransforms/logicalassignment.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type logicalAssignmentTransformer struct { + transformers.Transformer +} + +func (ch *logicalAssignmentTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newLogicalAssignmentTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &logicalAssignmentTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/namedevaluation.go b/internal/transformers/estransforms/namedevaluation.go similarity index 99% rename from internal/transformers/namedevaluation.go rename to internal/transformers/estransforms/namedevaluation.go index dddd5c535d..e35851b39c 100644 --- a/internal/transformers/namedevaluation.go +++ b/internal/transformers/estransforms/namedevaluation.go @@ -1,4 +1,4 @@ -package transformers +package estransforms import ( "slices" diff --git a/internal/transformers/estransforms/nullishcoalescing.go b/internal/transformers/estransforms/nullishcoalescing.go new file mode 100644 index 0000000000..84b3ddccb2 --- /dev/null +++ b/internal/transformers/estransforms/nullishcoalescing.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type nullishCoalescingTransformer struct { + transformers.Transformer +} + +func (ch *nullishCoalescingTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newNullishCoalescingTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &nullishCoalescingTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/objectrestspread.go b/internal/transformers/estransforms/objectrestspread.go new file mode 100644 index 0000000000..0b007f02c8 --- /dev/null +++ b/internal/transformers/estransforms/objectrestspread.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type objectRestSpreadTransformer struct { + transformers.Transformer +} + +func (ch *objectRestSpreadTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newObjectRestSpreadTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &objectRestSpreadTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/optionalcatch.go b/internal/transformers/estransforms/optionalcatch.go new file mode 100644 index 0000000000..aabd41377a --- /dev/null +++ b/internal/transformers/estransforms/optionalcatch.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type optionalCatchTransformer struct { + transformers.Transformer +} + +func (ch *optionalCatchTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newOptionalCatchTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &optionalCatchTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/estransforms/optionalchain.go b/internal/transformers/estransforms/optionalchain.go new file mode 100644 index 0000000000..634ae61d2f --- /dev/null +++ b/internal/transformers/estransforms/optionalchain.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +type optionalChainTransformer struct { + transformers.Transformer +} + +func (ch *optionalChainTransformer) visit(node *ast.Node) *ast.Node { + return node // !!! +} + +func newOptionalChainTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &optionalChainTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} diff --git a/internal/transformers/esnext.go b/internal/transformers/estransforms/using.go similarity index 58% rename from internal/transformers/esnext.go rename to internal/transformers/estransforms/using.go index 8d084fa3bc..bd18dbacca 100644 --- a/internal/transformers/esnext.go +++ b/internal/transformers/estransforms/using.go @@ -1,4 +1,4 @@ -package transformers +package estransforms import ( "maps" @@ -7,10 +7,11 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) -type ESNextTransformer struct { - Transformer +type usingDeclarationTransformer struct { + transformers.Transformer exportBindings map[string]*ast.ExportSpecifierNode exportVars []*ast.VariableDeclarationNode @@ -18,6 +19,11 @@ type ESNextTransformer struct { exportEqualsBinding *ast.IdentifierNode } +func newUsingDeclarationTransformer(emitContext *printer.EmitContext) *transformers.Transformer { + tx := &usingDeclarationTransformer{} + return tx.NewTransformer(tx.visit, emitContext) +} + type usingKind uint const ( @@ -26,12 +32,7 @@ const ( usingKindAsync ) -func NewESNextTransformer(emitContext *printer.EmitContext) *Transformer { - tx := &ESNextTransformer{} - return tx.NewTransformer(tx.visit, emitContext) -} - -func (tx *ESNextTransformer) visit(node *ast.Node) *ast.Node { +func (tx *usingDeclarationTransformer) visit(node *ast.Node) *ast.Node { if node.SubtreeFacts()&ast.SubtreeContainsESNext == 0 { return node } @@ -48,12 +49,12 @@ func (tx *ESNextTransformer) visit(node *ast.Node) *ast.Node { case ast.KindSwitchStatement: node = tx.visitSwitchStatement(node.AsSwitchStatement()) default: - node = tx.visitor.VisitEachChild(node) + node = tx.Visitor().VisitEachChild(node) } return node } -func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { +func (tx *usingDeclarationTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { if node.IsDeclarationFile { return node.AsNode() } @@ -99,14 +100,14 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { // statements in the source file into the `try` block, which is the same approach we use for System module // emit. Unlike System module emit, we attempt to preserve all statements prior to the first top-level // `using` to isolate the complexity of the transformed output to only where it is necessary. - tx.emitContext.StartVariableEnvironment() + tx.EmitContext().StartVariableEnvironment() tx.exportBindings = make(map[string]*ast.ExportSpecifierNode) tx.exportVars = nil - prologue, rest := tx.factory.SplitStandardPrologue(node.Statements.Nodes) + prologue, rest := tx.Factory().SplitStandardPrologue(node.Statements.Nodes) var topLevelStatements []*ast.Statement - topLevelStatements = append(topLevelStatements, core.FirstResult(tx.visitor.VisitSlice(prologue))...) + topLevelStatements = append(topLevelStatements, core.FirstResult(tx.Visitor().VisitSlice(prologue))...) // Collect and transform any leading statements up to the first `using` or `await using`. This preserves // the original statement order much as is possible. @@ -116,7 +117,7 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { statement := rest[pos] if getUsingKind(statement) != usingKindNone { if pos > 0 { - topLevelStatements = append(topLevelStatements, core.FirstResult(tx.visitor.VisitSlice(rest[:pos]))...) + topLevelStatements = append(topLevelStatements, core.FirstResult(tx.Visitor().VisitSlice(rest[:pos]))...) } break } @@ -135,11 +136,11 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { if len(tx.exportBindings) > 0 { topLevelStatements = append( topLevelStatements, - tx.factory.NewExportDeclaration( + tx.Factory().NewExportDeclaration( nil, /*modifiers*/ false, /*isTypeOnly*/ - tx.factory.NewNamedExports( - tx.factory.NewNodeList( + tx.Factory().NewNamedExports( + tx.Factory().NewNodeList( slices.Collect(maps.Values(tx.exportBindings)), ), ), @@ -149,22 +150,22 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { ) } - topLevelStatements = tx.emitContext.EndAndMergeVariableEnvironment(topLevelStatements) + topLevelStatements = tx.EmitContext().EndAndMergeVariableEnvironment(topLevelStatements) if len(tx.exportVars) > 0 { - topLevelStatements = append(topLevelStatements, tx.factory.NewVariableStatement( - tx.factory.NewModifierList([]*ast.Node{ - tx.factory.NewModifier(ast.KindExportKeyword), + topLevelStatements = append(topLevelStatements, tx.Factory().NewVariableStatement( + tx.Factory().NewModifierList([]*ast.Node{ + tx.Factory().NewModifier(ast.KindExportKeyword), }), - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsLet, - tx.factory.NewNodeList(tx.exportVars), + tx.Factory().NewNodeList(tx.exportVars), ), )) } topLevelStatements = append(topLevelStatements, tx.createDownlevelUsingStatements(bodyStatements, envBinding, usingKind == usingKindAsync)...) if tx.exportEqualsBinding != nil { - topLevelStatements = append(topLevelStatements, tx.factory.NewExportAssignment( + topLevelStatements = append(topLevelStatements, tx.Factory().NewExportAssignment( nil, /*modifiers*/ true, /*isExportEquals*/ nil, /*typeNode*/ @@ -172,11 +173,11 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { )) } - visited = tx.factory.UpdateSourceFile(node, tx.factory.NewNodeList(topLevelStatements)) + visited = tx.Factory().UpdateSourceFile(node, tx.Factory().NewNodeList(topLevelStatements)) } else { - visited = tx.visitor.VisitEachChild(node.AsNode()) + visited = tx.Visitor().VisitEachChild(node.AsNode()) } - tx.emitContext.AddEmitHelper(visited, tx.emitContext.ReadEmitHelpers()...) + tx.EmitContext().AddEmitHelper(visited, tx.EmitContext().ReadEmitHelpers()...) tx.exportVars = nil tx.exportBindings = nil tx.defaultExportBinding = nil @@ -184,26 +185,26 @@ func (tx *ESNextTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { return visited } -func (tx *ESNextTransformer) visitBlock(node *ast.Block) *ast.Node { +func (tx *usingDeclarationTransformer) visitBlock(node *ast.Block) *ast.Node { usingKind := getUsingKindOfStatements(node.Statements.Nodes) if usingKind != usingKindNone { - prologue, rest := tx.factory.SplitStandardPrologue(node.Statements.Nodes) + prologue, rest := tx.Factory().SplitStandardPrologue(node.Statements.Nodes) envBinding := tx.createEnvBinding() statements := make([]*ast.Statement, 0, len(prologue)+2) - statements = append(statements, core.FirstResult(tx.visitor.VisitSlice(prologue))...) + statements = append(statements, core.FirstResult(tx.Visitor().VisitSlice(prologue))...) statements = append(statements, tx.createDownlevelUsingStatements( tx.transformUsingDeclarations(rest, envBinding, nil /*topLevelStatements*/), envBinding, usingKind == usingKindAsync, )...) - statementList := tx.factory.NewNodeList(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = node.Statements.Loc - return tx.factory.UpdateBlock(node, statementList) + return tx.Factory().UpdateBlock(node, statementList) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } -func (tx *ESNextTransformer) visitForStatement(node *ast.ForStatement) *ast.Node { +func (tx *usingDeclarationTransformer) visitForStatement(node *ast.ForStatement) *ast.Node { if node.Initializer != nil && isUsingVariableDeclarationList(node.Initializer) { // given: // @@ -217,10 +218,10 @@ func (tx *ESNextTransformer) visitForStatement(node *ast.ForStatement) *ast.Node // } // // before handing the shallow transformation back to the visitor for an in-depth transformation. - return tx.visitor.VisitNode( - tx.factory.NewBlock(tx.factory.NewNodeList([]*ast.Statement{ - tx.factory.NewVariableStatement(nil /*modifiers*/, node.Initializer), - tx.factory.UpdateForStatement( + return tx.Visitor().VisitNode( + tx.Factory().NewBlock(tx.Factory().NewNodeList([]*ast.Statement{ + tx.Factory().NewVariableStatement(nil /*modifiers*/, node.Initializer), + tx.Factory().UpdateForStatement( node, nil, /*initializer*/ node.Condition, @@ -230,10 +231,10 @@ func (tx *ESNextTransformer) visitForStatement(node *ast.ForStatement) *ast.Node }), false /*multiLine*/), ) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } -func (tx *ESNextTransformer) visitForOfStatement(node *ast.ForInOrOfStatement) *ast.Node { +func (tx *usingDeclarationTransformer) visitForOfStatement(node *ast.ForInOrOfStatement) *ast.Node { if isUsingVariableDeclarationList(node.Initializer) { // given: // @@ -250,43 +251,43 @@ func (tx *ESNextTransformer) visitForOfStatement(node *ast.ForInOrOfStatement) * forInitializer := node.Initializer.AsVariableDeclarationList() forDecl := core.FirstOrNil(forInitializer.Declarations.Nodes) if forDecl == nil { - forDecl = tx.factory.NewVariableDeclaration(tx.factory.NewTempVariable(), nil, nil, nil) + forDecl = tx.Factory().NewVariableDeclaration(tx.Factory().NewTempVariable(), nil, nil, nil) } isAwaitUsing := getUsingKindOfVariableDeclarationList(forInitializer) == usingKindAsync - temp := tx.factory.NewGeneratedNameForNode(forDecl.Name()) - usingVar := tx.factory.UpdateVariableDeclaration(forDecl.AsVariableDeclaration(), forDecl.Name(), nil /*exclamationToken*/, nil /*type*/, temp) - usingVarList := tx.factory.NewVariableDeclarationList( + temp := tx.Factory().NewGeneratedNameForNode(forDecl.Name()) + usingVar := tx.Factory().UpdateVariableDeclaration(forDecl.AsVariableDeclaration(), forDecl.Name(), nil /*exclamationToken*/, nil /*type*/, temp) + usingVarList := tx.Factory().NewVariableDeclarationList( core.IfElse(isAwaitUsing, ast.NodeFlagsAwaitUsing, ast.NodeFlagsUsing), - tx.factory.NewNodeList([]*ast.Node{usingVar}), + tx.Factory().NewNodeList([]*ast.Node{usingVar}), ) - usingVarStatement := tx.factory.NewVariableStatement(nil /*modifiers*/, usingVarList) + usingVarStatement := tx.Factory().NewVariableStatement(nil /*modifiers*/, usingVarList) var statement *ast.Statement if ast.IsBlock(node.Statement) { statements := make([]*ast.Statement, 0, len(node.Statement.AsBlock().Statements.Nodes)+1) statements = append(statements, usingVarStatement) statements = append(statements, node.Statement.AsBlock().Statements.Nodes...) - statement = tx.factory.UpdateBlock( + statement = tx.Factory().UpdateBlock( node.Statement.AsBlock(), - tx.factory.NewNodeList(statements), + tx.Factory().NewNodeList(statements), ) } else { - statement = tx.factory.NewBlock( - tx.factory.NewNodeList([]*ast.Statement{ + statement = tx.Factory().NewBlock( + tx.Factory().NewNodeList([]*ast.Statement{ usingVarStatement, node.Statement, }), true, /*multiLine*/ ) } - return tx.visitor.VisitNode( - tx.factory.UpdateForInOrOfStatement( + return tx.Visitor().VisitNode( + tx.Factory().UpdateForInOrOfStatement( node, node.AwaitModifier, - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.VariableDeclarationNode{ - tx.factory.NewVariableDeclaration(temp, nil /*exclamationToken*/, nil /*type*/, nil), + tx.Factory().NewNodeList([]*ast.VariableDeclarationNode{ + tx.Factory().NewVariableDeclaration(temp, nil /*exclamationToken*/, nil /*type*/, nil), }), ), node.Expression, @@ -294,21 +295,21 @@ func (tx *ESNextTransformer) visitForOfStatement(node *ast.ForInOrOfStatement) * ), ) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } -func (tx *ESNextTransformer) visitCaseOrDefaultClause(node *ast.CaseOrDefaultClause, envBinding *ast.IdentifierNode) *ast.Node { +func (tx *usingDeclarationTransformer) visitCaseOrDefaultClause(node *ast.CaseOrDefaultClause, envBinding *ast.IdentifierNode) *ast.Node { if getUsingKindOfStatements(node.Statements.Nodes) != usingKindNone { - return tx.factory.UpdateCaseOrDefaultClause( + return tx.Factory().UpdateCaseOrDefaultClause( node, - tx.visitor.VisitNode(node.Expression), - tx.factory.NewNodeList(tx.transformUsingDeclarations(node.Statements.Nodes, envBinding, nil /*topLevelStatements*/)), + tx.Visitor().VisitNode(node.Expression), + tx.Factory().NewNodeList(tx.transformUsingDeclarations(node.Statements.Nodes, envBinding, nil /*topLevelStatements*/)), ) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } -func (tx *ESNextTransformer) visitSwitchStatement(node *ast.SwitchStatement) *ast.Node { +func (tx *usingDeclarationTransformer) visitSwitchStatement(node *ast.SwitchStatement) *ast.Node { // given: // // switch (expr) { @@ -336,14 +337,14 @@ func (tx *ESNextTransformer) visitSwitchStatement(node *ast.SwitchStatement) *as usingKind := getUsingKindOfCaseOrDefaultClauses(node.CaseBlock.AsCaseBlock().Clauses.Nodes) if usingKind != usingKindNone { envBinding := tx.createEnvBinding() - return singleOrMany(tx.createDownlevelUsingStatements( + return transformers.SingleOrMany(tx.createDownlevelUsingStatements( []*ast.Statement{ - tx.factory.UpdateSwitchStatement( + tx.Factory().UpdateSwitchStatement( node, - tx.visitor.VisitNode(node.Expression), - tx.factory.UpdateCaseBlock( + tx.Visitor().VisitNode(node.Expression), + tx.Factory().UpdateCaseBlock( node.CaseBlock.AsCaseBlock(), - tx.factory.NewNodeList( + tx.Factory().NewNodeList( core.Map(node.CaseBlock.AsCaseBlock().Clauses.Nodes, func(clause *ast.CaseOrDefaultClauseNode) *ast.CaseOrDefaultClauseNode { return tx.visitCaseOrDefaultClause(clause.AsCaseOrDefaultClause(), envBinding) }), @@ -353,13 +354,13 @@ func (tx *ESNextTransformer) visitSwitchStatement(node *ast.SwitchStatement) *as }, envBinding, usingKind == usingKindAsync, - ), tx.factory) + ), tx.Factory()) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } -func (tx *ESNextTransformer) transformUsingDeclarations(statementsIn []*ast.Statement, envBinding *ast.IdentifierNode, topLevelStatements *[]*ast.Statement) []*ast.Node { +func (tx *usingDeclarationTransformer) transformUsingDeclarations(statementsIn []*ast.Statement, envBinding *ast.IdentifierNode, topLevelStatements *[]*ast.Statement) []*ast.Node { var statements []*ast.Statement hoist := func(node *ast.Statement) *ast.Statement { @@ -406,20 +407,20 @@ func (tx *ESNextTransformer) transformUsingDeclarations(statementsIn []*ast.Stat } // perform a shallow transform for any named evaluation - if isNamedEvaluation(tx.emitContext, declaration) { - declaration = transformNamedEvaluation(tx.emitContext, declaration, false /*ignoreEmptyStringLiteral*/, "" /*assignedName*/) + if isNamedEvaluation(tx.EmitContext(), declaration) { + declaration = transformNamedEvaluation(tx.EmitContext(), declaration, false /*ignoreEmptyStringLiteral*/, "" /*assignedName*/) } - initializer := tx.visitor.VisitNode(declaration.Initializer()) + initializer := tx.Visitor().VisitNode(declaration.Initializer()) if initializer == nil { - initializer = tx.factory.NewVoidZeroExpression() + initializer = tx.Factory().NewVoidZeroExpression() } - declarations = append(declarations, tx.factory.UpdateVariableDeclaration( + declarations = append(declarations, tx.Factory().UpdateVariableDeclaration( declaration.AsVariableDeclaration(), declaration.Name(), nil, /*exclamationToken*/ nil, /*type*/ - tx.factory.NewAddDisposableResourceHelper( + tx.Factory().NewAddDisposableResourceHelper( envBinding, initializer, usingKind == usingKindAsync, @@ -429,10 +430,10 @@ func (tx *ESNextTransformer) transformUsingDeclarations(statementsIn []*ast.Stat // Only replace the statement if it was valid. if len(declarations) > 0 { - varList := tx.factory.NewVariableDeclarationList(ast.NodeFlagsConst, tx.factory.NewNodeList(declarations)) - tx.emitContext.SetOriginal(varList, declarationList) + varList := tx.Factory().NewVariableDeclarationList(ast.NodeFlagsConst, tx.Factory().NewNodeList(declarations)) + tx.EmitContext().SetOriginal(varList, declarationList) varList.Loc = declarationList.Loc - hoistOrAppendNode(tx.factory.UpdateVariableStatement(varStatement, nil /*modifiers*/, varList)) + hoistOrAppendNode(tx.Factory().UpdateVariableStatement(varStatement, nil /*modifiers*/, varList)) continue } } @@ -450,12 +451,12 @@ func (tx *ESNextTransformer) transformUsingDeclarations(statementsIn []*ast.Stat return statements } -func (tx *ESNextTransformer) hoistImportOrExportOrHoistedDeclaration(node *ast.Statement, topLevelStatements *[]*ast.Statement) { +func (tx *usingDeclarationTransformer) hoistImportOrExportOrHoistedDeclaration(node *ast.Statement, topLevelStatements *[]*ast.Statement) { // NOTE: `node` has already been visited *topLevelStatements = append(*topLevelStatements, node) } -func (tx *ESNextTransformer) hoistExportAssignment(node *ast.ExportAssignment) *ast.Statement { +func (tx *usingDeclarationTransformer) hoistExportAssignment(node *ast.ExportAssignment) *ast.Statement { if node.IsExportEquals { return tx.hoistExportEquals(node) } else { @@ -463,7 +464,7 @@ func (tx *ESNextTransformer) hoistExportAssignment(node *ast.ExportAssignment) * } } -func (tx *ESNextTransformer) hoistExportDefault(node *ast.ExportAssignment) *ast.Statement { +func (tx *usingDeclarationTransformer) hoistExportDefault(node *ast.ExportAssignment) *ast.Statement { // NOTE: `node` has already been visited if tx.defaultExportBinding != nil { // invalid case of multiple `export default` declarations. Don't assert here, just pass it through @@ -483,22 +484,22 @@ func (tx *ESNextTransformer) hoistExportDefault(node *ast.ExportAssignment) *ast // // body // default_1 = expr; - tx.defaultExportBinding = tx.factory.NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) - tx.hoistBindingIdentifier(tx.defaultExportBinding /*isExport*/, true, tx.factory.NewIdentifier("default"), node.AsNode()) + tx.defaultExportBinding = tx.Factory().NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) + tx.hoistBindingIdentifier(tx.defaultExportBinding /*isExport*/, true, tx.Factory().NewIdentifier("default"), node.AsNode()) // give a class or function expression an assigned name, if needed. expression := node.Expression innerExpression := ast.SkipOuterExpressions(expression, ast.OEKAll) - if isNamedEvaluation(tx.emitContext, innerExpression) { - innerExpression = transformNamedEvaluation(tx.emitContext, innerExpression /*ignoreEmptyStringLiteral*/, false, "default") - expression = tx.factory.RestoreOuterExpressions(expression, innerExpression, ast.OEKAll) + if isNamedEvaluation(tx.EmitContext(), innerExpression) { + innerExpression = transformNamedEvaluation(tx.EmitContext(), innerExpression /*ignoreEmptyStringLiteral*/, false, "default") + expression = tx.Factory().RestoreOuterExpressions(expression, innerExpression, ast.OEKAll) } - assignment := tx.factory.NewAssignmentExpression(tx.defaultExportBinding, expression) - return tx.factory.NewExpressionStatement(assignment) + assignment := tx.Factory().NewAssignmentExpression(tx.defaultExportBinding, expression) + return tx.Factory().NewExpressionStatement(assignment) } -func (tx *ESNextTransformer) hoistExportEquals(node *ast.ExportAssignment) *ast.Statement { +func (tx *usingDeclarationTransformer) hoistExportEquals(node *ast.ExportAssignment) *ast.Statement { // NOTE: `node` has already been visited if tx.exportEqualsBinding != nil { // invalid case of multiple `export default` declarations. Don't assert here, just pass it through @@ -522,15 +523,15 @@ func (tx *ESNextTransformer) hoistExportEquals(node *ast.ExportAssignment) *ast. // // top level suffix // export = default_1; - tx.exportEqualsBinding = tx.factory.NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) - tx.emitContext.AddVariableDeclaration(tx.exportEqualsBinding) + tx.exportEqualsBinding = tx.Factory().NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) + tx.EmitContext().AddVariableDeclaration(tx.exportEqualsBinding) // give a class or function expression an assigned name, if needed. - assignment := tx.factory.NewAssignmentExpression(tx.exportEqualsBinding, node.Expression) - return tx.factory.NewExpressionStatement(assignment) + assignment := tx.Factory().NewAssignmentExpression(tx.exportEqualsBinding, node.Expression) + return tx.Factory().NewExpressionStatement(assignment) } -func (tx *ESNextTransformer) hoistClassDeclaration(node *ast.ClassDeclaration) *ast.Statement { +func (tx *usingDeclarationTransformer) hoistClassDeclaration(node *ast.ClassDeclaration) *ast.Statement { // NOTE: `node` has already been visited if node.Name() == nil && tx.defaultExportBinding != nil { // invalid case of multiple `export default` declarations. Don't assert here, just pass it through @@ -542,7 +543,7 @@ func (tx *ESNextTransformer) hoistClassDeclaration(node *ast.ClassDeclaration) * // When hoisting a class declaration at the top level of a file containing a top-level `using` statement, we // must first convert it to a class expression so that we can hoist the binding outside of the `try`. - expression := convertClassDeclarationToClassExpression(tx.emitContext, node) + expression := convertClassDeclarationToClassExpression(tx.EmitContext(), node) if node.Name() != nil { // given: // @@ -566,13 +567,13 @@ func (tx *ESNextTransformer) hoistClassDeclaration(node *ast.ClassDeclaration) * // } // // If the class is exported, we also produce an `export { C };` - tx.hoistBindingIdentifier(tx.factory.GetLocalName(node.AsNode()), isExported && !isDefault, nil /*exportAlias*/, node.AsNode()) - expression = tx.factory.NewAssignmentExpression(tx.factory.GetDeclarationName(node.AsNode()), expression) - tx.emitContext.SetOriginal(expression, node.AsNode()) - tx.emitContext.SetSourceMapRange(expression, node.Loc) - tx.emitContext.SetCommentRange(expression, node.Loc) - if isNamedEvaluation(tx.emitContext, expression) { - expression = transformNamedEvaluation(tx.emitContext, expression, false /*ignoreEmptyStringLiteral*/, "" /*assignedName*/) + tx.hoistBindingIdentifier(tx.Factory().GetLocalName(node.AsNode()), isExported && !isDefault, nil /*exportAlias*/, node.AsNode()) + expression = tx.Factory().NewAssignmentExpression(tx.Factory().GetDeclarationName(node.AsNode()), expression) + tx.EmitContext().SetOriginal(expression, node.AsNode()) + tx.EmitContext().SetSourceMapRange(expression, node.Loc) + tx.EmitContext().SetCommentRange(expression, node.Loc) + if isNamedEvaluation(tx.EmitContext(), expression) { + expression = transformNamedEvaluation(tx.EmitContext(), expression, false /*ignoreEmptyStringLiteral*/, "" /*assignedName*/) } } @@ -603,19 +604,19 @@ func (tx *ESNextTransformer) hoistClassDeclaration(node *ast.ClassDeclaration) * // } // // Though we will never reassign `default_1`, this most closely matches the specified runtime semantics. - tx.defaultExportBinding = tx.factory.NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) - tx.hoistBindingIdentifier(tx.defaultExportBinding /*isExport*/, true, tx.factory.NewIdentifier("default"), node.AsNode()) - expression = tx.factory.NewAssignmentExpression(tx.defaultExportBinding, expression) - tx.emitContext.SetOriginal(expression, node.AsNode()) - if isNamedEvaluation(tx.emitContext, expression) { - expression = transformNamedEvaluation(tx.emitContext, expression /*ignoreEmptyStringLiteral*/, false, "default") + tx.defaultExportBinding = tx.Factory().NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsOptimistic}) + tx.hoistBindingIdentifier(tx.defaultExportBinding /*isExport*/, true, tx.Factory().NewIdentifier("default"), node.AsNode()) + expression = tx.Factory().NewAssignmentExpression(tx.defaultExportBinding, expression) + tx.EmitContext().SetOriginal(expression, node.AsNode()) + if isNamedEvaluation(tx.EmitContext(), expression) { + expression = transformNamedEvaluation(tx.EmitContext(), expression /*ignoreEmptyStringLiteral*/, false, "default") } } - return tx.factory.NewExpressionStatement(expression) + return tx.Factory().NewExpressionStatement(expression) } -func (tx *ESNextTransformer) hoistVariableStatement(node *ast.VariableStatement) *ast.Statement { +func (tx *usingDeclarationTransformer) hoistVariableStatement(node *ast.VariableStatement) *ast.Statement { // NOTE: `node` has already been visited var expressions []*ast.Expression isExported := ast.HasSyntacticModifier(node.AsNode(), ast.ModifierFlagsExport) @@ -626,36 +627,36 @@ func (tx *ESNextTransformer) hoistVariableStatement(node *ast.VariableStatement) } } if len(expressions) > 0 { - statement := tx.factory.NewExpressionStatement(tx.factory.InlineExpressions(expressions)) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.SetCommentRange(statement, node.Loc) - tx.emitContext.SetSourceMapRange(statement, node.Loc) + statement := tx.Factory().NewExpressionStatement(tx.Factory().InlineExpressions(expressions)) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().SetCommentRange(statement, node.Loc) + tx.EmitContext().SetSourceMapRange(statement, node.Loc) return statement } return nil } -func (tx *ESNextTransformer) hoistInitializedVariable(node *ast.VariableDeclaration) *ast.Expression { +func (tx *usingDeclarationTransformer) hoistInitializedVariable(node *ast.VariableDeclaration) *ast.Expression { // NOTE: `node` has already been visited if node.Initializer == nil { panic("Expected initializer") } var target *ast.Expression if ast.IsIdentifier(node.Name()) { - target = node.Name().Clone(tx.factory) - tx.emitContext.SetEmitFlags(target, tx.emitContext.EmitFlags(target) & ^(printer.EFLocalName|printer.EFExportName|printer.EFInternalName)) + target = node.Name().Clone(tx.Factory()) + tx.EmitContext().SetEmitFlags(target, tx.EmitContext().EmitFlags(target) & ^(printer.EFLocalName|printer.EFExportName|printer.EFInternalName)) } else { - target = convertBindingPatternToAssignmentPattern(tx.emitContext, node.Name().AsBindingPattern()) + target = transformers.ConvertBindingPatternToAssignmentPattern(tx.EmitContext(), node.Name().AsBindingPattern()) } - assignment := tx.factory.NewAssignmentExpression(target, node.Initializer) - tx.emitContext.SetOriginal(assignment, node.AsNode()) - tx.emitContext.SetCommentRange(assignment, node.Loc) - tx.emitContext.SetSourceMapRange(assignment, node.Loc) + assignment := tx.Factory().NewAssignmentExpression(target, node.Initializer) + tx.EmitContext().SetOriginal(assignment, node.AsNode()) + tx.EmitContext().SetCommentRange(assignment, node.Loc) + tx.EmitContext().SetSourceMapRange(assignment, node.Loc) return assignment } -func (tx *ESNextTransformer) hoistBindingElement(node *ast.Node /*VariableDeclaration|BindingElement*/, isExportedDeclaration bool, original *ast.Node) { +func (tx *usingDeclarationTransformer) hoistBindingElement(node *ast.Node /*VariableDeclaration|BindingElement*/, isExportedDeclaration bool, original *ast.Node) { // NOTE: `node` has already been visited if ast.IsBindingPattern(node.Name()) { for _, element := range node.Name().AsBindingPattern().Elements.Nodes { @@ -668,17 +669,17 @@ func (tx *ESNextTransformer) hoistBindingElement(node *ast.Node /*VariableDeclar } } -func (tx *ESNextTransformer) hoistBindingIdentifier(node *ast.IdentifierNode, isExport bool, exportAlias *ast.IdentifierNode, original *ast.Node) { +func (tx *usingDeclarationTransformer) hoistBindingIdentifier(node *ast.IdentifierNode, isExport bool, exportAlias *ast.IdentifierNode, original *ast.Node) { // NOTE: `node` has already been visited name := node - if !isGeneratedIdentifier(tx.emitContext, node) { - name = name.Clone(tx.factory) + if !transformers.IsGeneratedIdentifier(tx.EmitContext(), node) { + name = name.Clone(tx.Factory()) } if isExport { - if exportAlias == nil && !isLocalName(tx.emitContext, name) { - varDecl := tx.factory.NewVariableDeclaration(name, nil /*exclamationToken*/, nil /*type*/, nil /*initializer*/) + if exportAlias == nil && !transformers.IsLocalName(tx.EmitContext(), name) { + varDecl := tx.Factory().NewVariableDeclaration(name, nil /*exclamationToken*/, nil /*type*/, nil /*initializer*/) if original != nil { - tx.emitContext.SetOriginal(varDecl, original) + tx.EmitContext().SetOriginal(varDecl, original) } tx.exportVars = append(tx.exportVars, varDecl) return @@ -692,37 +693,37 @@ func (tx *ESNextTransformer) hoistBindingIdentifier(node *ast.IdentifierNode, is } else { exportName = name } - specifier := tx.factory.NewExportSpecifier( /*isTypeOnly*/ false, localName, exportName) + specifier := tx.Factory().NewExportSpecifier( /*isTypeOnly*/ false, localName, exportName) if original != nil { - tx.emitContext.SetOriginal(specifier, original) + tx.EmitContext().SetOriginal(specifier, original) } if tx.exportBindings == nil { tx.exportBindings = make(map[string]*ast.ExportSpecifierNode) } tx.exportBindings[name.Text()] = specifier } - tx.emitContext.AddVariableDeclaration(name) + tx.EmitContext().AddVariableDeclaration(name) } -func (tx *ESNextTransformer) createEnvBinding() *ast.IdentifierNode { - return tx.factory.NewUniqueName("env") +func (tx *usingDeclarationTransformer) createEnvBinding() *ast.IdentifierNode { + return tx.Factory().NewUniqueName("env") } -func (tx *ESNextTransformer) createDownlevelUsingStatements(bodyStatements []*ast.Node, envBinding *ast.IdentifierNode, async bool) []*ast.Statement { +func (tx *usingDeclarationTransformer) createDownlevelUsingStatements(bodyStatements []*ast.Node, envBinding *ast.IdentifierNode, async bool) []*ast.Statement { statements := make([]*ast.Statement, 0, 2) // produces: // // const env_1 = { stack: [], error: void 0, hasError: false }; // - envObject := tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Expression{ - tx.factory.NewPropertyAssignment(nil /*modifiers*/, tx.factory.NewIdentifier("stack"), nil /*postfixToken*/, nil /*typeNode*/, tx.factory.NewArrayLiteralExpression(nil, false /*multiLine*/)), - tx.factory.NewPropertyAssignment(nil /*modifiers*/, tx.factory.NewIdentifier("error"), nil /*postfixToken*/, nil /*typeNode*/, tx.factory.NewVoidZeroExpression()), - tx.factory.NewPropertyAssignment(nil /*modifiers*/, tx.factory.NewIdentifier("hasError"), nil /*postfixToken*/, nil /*typeNode*/, tx.factory.NewFalseExpression()), + envObject := tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Expression{ + tx.Factory().NewPropertyAssignment(nil /*modifiers*/, tx.Factory().NewIdentifier("stack"), nil /*postfixToken*/, nil /*typeNode*/, tx.Factory().NewArrayLiteralExpression(nil, false /*multiLine*/)), + tx.Factory().NewPropertyAssignment(nil /*modifiers*/, tx.Factory().NewIdentifier("error"), nil /*postfixToken*/, nil /*typeNode*/, tx.Factory().NewVoidZeroExpression()), + tx.Factory().NewPropertyAssignment(nil /*modifiers*/, tx.Factory().NewIdentifier("hasError"), nil /*postfixToken*/, nil /*typeNode*/, tx.Factory().NewFalseExpression()), }), false /*multiLine*/) - envVar := tx.factory.NewVariableDeclaration(envBinding, nil /*exclamationToken*/, nil /*typeNode*/, envObject) - envVarList := tx.factory.NewVariableDeclarationList(ast.NodeFlagsConst, tx.factory.NewNodeList([]*ast.VariableDeclarationNode{envVar})) - envVarStatement := tx.factory.NewVariableStatement(nil /*modifiers*/, envVarList) + envVar := tx.Factory().NewVariableDeclaration(envBinding, nil /*exclamationToken*/, nil /*typeNode*/, envObject) + envVarList := tx.Factory().NewVariableDeclarationList(ast.NodeFlagsConst, tx.Factory().NewNodeList([]*ast.VariableDeclarationNode{envVar})) + envVarStatement := tx.Factory().NewVariableStatement(nil /*modifiers*/, envVarList) statements = append(statements, envVarStatement) // when `async` is `false`, produces: @@ -756,26 +757,26 @@ func (tx *ESNextTransformer) createDownlevelUsingStatements(bodyStatements []*as // Unfortunately, it is necessary to use two properties to indicate an error because `throw undefined` is legal // JavaScript. - tryBlock := tx.factory.NewBlock(tx.factory.NewNodeList(bodyStatements), true /*multiLine*/) - bodyCatchBinding := tx.factory.NewUniqueName("e") - catchClause := tx.factory.NewCatchClause( - tx.factory.NewVariableDeclaration( + tryBlock := tx.Factory().NewBlock(tx.Factory().NewNodeList(bodyStatements), true /*multiLine*/) + bodyCatchBinding := tx.Factory().NewUniqueName("e") + catchClause := tx.Factory().NewCatchClause( + tx.Factory().NewVariableDeclaration( bodyCatchBinding, nil, /*exclamationToken*/ nil, /*type*/ nil, /*initializer*/ ), - tx.factory.NewBlock(tx.factory.NewNodeList([]*ast.Statement{ - tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewPropertyAccessExpression(envBinding, nil, tx.factory.NewIdentifier("error"), ast.NodeFlagsNone), + tx.Factory().NewBlock(tx.Factory().NewNodeList([]*ast.Statement{ + tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewPropertyAccessExpression(envBinding, nil, tx.Factory().NewIdentifier("error"), ast.NodeFlagsNone), bodyCatchBinding, ), ), - tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewPropertyAccessExpression(envBinding, nil, tx.factory.NewIdentifier("hasError"), ast.NodeFlagsNone), - tx.factory.NewTrueExpression(), + tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewPropertyAccessExpression(envBinding, nil, tx.Factory().NewIdentifier("hasError"), ast.NodeFlagsNone), + tx.Factory().NewTrueExpression(), ), ), }), true /*multiLine*/), @@ -783,30 +784,30 @@ func (tx *ESNextTransformer) createDownlevelUsingStatements(bodyStatements []*as var finallyBlock *ast.BlockNode if async { - result := tx.factory.NewUniqueName("result") - finallyBlock = tx.factory.NewBlock(tx.factory.NewNodeList([]*ast.Statement{ - tx.factory.NewVariableStatement( + result := tx.Factory().NewUniqueName("result") + finallyBlock = tx.Factory().NewBlock(tx.Factory().NewNodeList([]*ast.Statement{ + tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList(ast.NodeFlagsConst, tx.factory.NewNodeList([]*ast.VariableDeclarationNode{ - tx.factory.NewVariableDeclaration( + tx.Factory().NewVariableDeclarationList(ast.NodeFlagsConst, tx.Factory().NewNodeList([]*ast.VariableDeclarationNode{ + tx.Factory().NewVariableDeclaration( result, nil, /*exclamationToken*/ nil, /*type*/ - tx.factory.NewDisposeResourcesHelper(envBinding), + tx.Factory().NewDisposeResourcesHelper(envBinding), ), })), ), - tx.factory.NewIfStatement(result, tx.factory.NewExpressionStatement(tx.factory.NewAwaitExpression(result)), nil /*elseStatement*/), + tx.Factory().NewIfStatement(result, tx.Factory().NewExpressionStatement(tx.Factory().NewAwaitExpression(result)), nil /*elseStatement*/), }), true /*multiLine*/) } else { - finallyBlock = tx.factory.NewBlock(tx.factory.NewNodeList([]*ast.Statement{ - tx.factory.NewExpressionStatement( - tx.factory.NewDisposeResourcesHelper(envBinding), + finallyBlock = tx.Factory().NewBlock(tx.Factory().NewNodeList([]*ast.Statement{ + tx.Factory().NewExpressionStatement( + tx.Factory().NewDisposeResourcesHelper(envBinding), ), }), true /*multiLine*/) } - tryStatement := tx.factory.NewTryStatement(tryBlock, catchClause, finallyBlock) + tryStatement := tx.Factory().NewTryStatement(tryBlock, catchClause, finallyBlock) statements = append(statements, tryStatement) return statements } diff --git a/internal/transformers/estransforms/utilities.go b/internal/transformers/estransforms/utilities.go new file mode 100644 index 0000000000..ec035e90c8 --- /dev/null +++ b/internal/transformers/estransforms/utilities.go @@ -0,0 +1,20 @@ +package estransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" +) + +func convertClassDeclarationToClassExpression(emitContext *printer.EmitContext, node *ast.ClassDeclaration) *ast.Expression { + updated := emitContext.Factory.NewClassExpression( + transformers.ExtractModifiers(emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault), + node.Name(), + node.TypeParameters, + node.HeritageClauses, + node.Members, + ) + emitContext.SetOriginal(updated, node.AsNode()) + updated.Loc = node.Loc + return updated +} diff --git a/internal/transformers/jsx.go b/internal/transformers/jsxtransforms/jsx.go similarity index 83% rename from internal/transformers/jsx.go rename to internal/transformers/jsxtransforms/jsx.go index e4f047016b..03fb5d8542 100644 --- a/internal/transformers/jsx.go +++ b/internal/transformers/jsxtransforms/jsx.go @@ -1,4 +1,4 @@ -package transformers +package jsxtransforms import ( "maps" @@ -13,10 +13,11 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/scanner" "github.com/microsoft/typescript-go/internal/stringutil" + "github.com/microsoft/typescript-go/internal/transformers" ) type JSXTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions emitResolver printer.EmitResolver @@ -28,7 +29,7 @@ type JSXTransformer struct { currentSourceFile *ast.SourceFile } -func NewJSXTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, emitResolver printer.EmitResolver) *Transformer { +func NewJSXTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, emitResolver printer.EmitResolver) *transformers.Transformer { tx := &JSXTransformer{ compilerOptions: compilerOptions, emitResolver: emitResolver, @@ -40,13 +41,13 @@ func (tx *JSXTransformer) getCurrentFileNameExpression() *ast.Node { if tx.filenameDeclaration != nil { return tx.filenameDeclaration.AsVariableDeclaration().Name() } - d := tx.factory.NewVariableDeclaration( - tx.factory.NewUniqueNameEx("_jsxFileName", printer.AutoGenerateOptions{ + d := tx.Factory().NewVariableDeclaration( + tx.Factory().NewUniqueNameEx("_jsxFileName", printer.AutoGenerateOptions{ Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel, }), nil, nil, - tx.factory.NewStringLiteral(tx.currentSourceFile.OriginalFileName()), + tx.Factory().NewStringLiteral(tx.currentSourceFile.OriginalFileName()), ) tx.filenameDeclaration = d return d.AsVariableDeclaration().Name() @@ -86,10 +87,10 @@ func (tx *JSXTransformer) getImplicitImportForName(name string) *ast.Node { tx.utilizedImplicitRuntimeImports[importSource] = make(map[string]*ast.Node) } - generatedName := tx.factory.NewUniqueNameEx("_"+name, printer.AutoGenerateOptions{ + generatedName := tx.Factory().NewUniqueNameEx("_"+name, printer.AutoGenerateOptions{ Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel | printer.GeneratedIdentifierFlagsAllowNameSubstitution, }) - specifier := tx.factory.NewImportSpecifier(false, tx.factory.NewIdentifier(name), generatedName) + specifier := tx.Factory().NewImportSpecifier(false, tx.Factory().NewIdentifier(name), generatedName) tx.emitResolver.SetReferencedImportDeclaration(generatedName, specifier) tx.utilizedImplicitRuntimeImports[importSource][name] = specifier return specifier.Name() @@ -128,7 +129,7 @@ func (tx *JSXTransformer) visit(node *ast.Node) *ast.Node { return tx.visitJsxExpression(node.AsJsxExpression()) } tx.setInChild(false) - return tx.visitor.VisitEachChild(node) // by default, do nothing + return tx.Visitor().VisitEachChild(node) // by default, do nothing } /** @@ -169,7 +170,7 @@ func insertStatementAfterPrologue[T any](to []*ast.Node, statement *ast.Node, is } func (tx *JSXTransformer) isAnyPrologueDirective(node *ast.Node) bool { - return ast.IsPrologueDirective(node) || (tx.emitContext.EmitFlags(node)&printer.EFCustomPrologue != 0) + return ast.IsPrologueDirective(node) || (tx.EmitContext().EmitFlags(node)&printer.EFCustomPrologue != 0) } func (tx *JSXTransformer) insertStatementAfterCustomPrologue(to []*ast.Node, statement *ast.Node) []*ast.Node { @@ -212,14 +213,14 @@ func (tx *JSXTransformer) visitSourceFile(file *ast.SourceFile) *ast.Node { tx.filenameDeclaration = nil tx.utilizedImplicitRuntimeImports = make(map[string]map[string]*ast.Node) - visited := tx.visitor.VisitEachChild(file.AsNode()) - tx.emitContext.AddEmitHelper(visited.AsNode(), tx.emitContext.ReadEmitHelpers()...) + visited := tx.Visitor().VisitEachChild(file.AsNode()) + tx.EmitContext().AddEmitHelper(visited.AsNode(), tx.EmitContext().ReadEmitHelpers()...) statements := visited.Statements() statementsUpdated := false if tx.filenameDeclaration != nil { - statements = tx.insertStatementAfterCustomPrologue(statements, tx.factory.NewVariableStatement(nil, tx.factory.NewVariableDeclarationList( + statements = tx.insertStatementAfterCustomPrologue(statements, tx.Factory().NewVariableStatement(nil, tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.Node{tx.filenameDeclaration}), + tx.Factory().NewNodeList([]*ast.Node{tx.filenameDeclaration}), ))) statementsUpdated = true } @@ -230,10 +231,10 @@ func (tx *JSXTransformer) visitSourceFile(file *ast.SourceFile) *ast.Node { statementsUpdated = true newStatements := make([]*ast.Node, 0, len(tx.utilizedImplicitRuntimeImports)) for importSource, importSpecifiersMap := range tx.utilizedImplicitRuntimeImports { - s := tx.factory.NewImportDeclaration( + s := tx.Factory().NewImportDeclaration( nil, - tx.factory.NewImportClause(false, nil, tx.factory.NewNamedImports(tx.factory.NewNodeList(getSortedSpecifiers(importSpecifiersMap)))), - tx.factory.NewStringLiteral(importSource), + tx.Factory().NewImportClause(false, nil, tx.Factory().NewNamedImports(tx.Factory().NewNodeList(getSortedSpecifiers(importSpecifiersMap)))), + tx.Factory().NewStringLiteral(importSource), nil, ) ast.SetParentInChildren(s) @@ -251,13 +252,13 @@ func (tx *JSXTransformer) visitSourceFile(file *ast.SourceFile) *ast.Node { sorted := getSortedSpecifiers(importSpecifiersMap) asBindingElems := make([]*ast.Node, 0, len(sorted)) for _, elem := range sorted { - asBindingElems = append(asBindingElems, tx.factory.NewBindingElement(nil, elem.AsImportSpecifier().PropertyName, elem.AsImportSpecifier().Name(), nil)) + asBindingElems = append(asBindingElems, tx.Factory().NewBindingElement(nil, elem.AsImportSpecifier().PropertyName, elem.AsImportSpecifier().Name(), nil)) } - s := tx.factory.NewVariableStatement(nil, tx.factory.NewVariableDeclarationList(ast.NodeFlagsConst, tx.factory.NewNodeList([]*ast.Node{tx.factory.NewVariableDeclaration( - tx.factory.NewBindingPattern(ast.KindObjectBindingPattern, tx.factory.NewNodeList(asBindingElems)), + s := tx.Factory().NewVariableStatement(nil, tx.Factory().NewVariableDeclarationList(ast.NodeFlagsConst, tx.Factory().NewNodeList([]*ast.Node{tx.Factory().NewVariableDeclaration( + tx.Factory().NewBindingPattern(ast.KindObjectBindingPattern, tx.Factory().NewNodeList(asBindingElems)), nil, nil, - tx.factory.NewCallExpression(tx.factory.NewIdentifier("require"), nil, nil, tx.factory.NewNodeList([]*ast.Node{tx.factory.NewStringLiteral(importSource)}), ast.NodeFlagsNone), + tx.Factory().NewCallExpression(tx.Factory().NewIdentifier("require"), nil, nil, tx.Factory().NewNodeList([]*ast.Node{tx.Factory().NewStringLiteral(importSource)}), ast.NodeFlagsNone), )}))) ast.SetParentInChildren(s) newStatements = append(newStatements, s) @@ -272,7 +273,7 @@ func (tx *JSXTransformer) visitSourceFile(file *ast.SourceFile) *ast.Node { } if statementsUpdated { - visited = tx.factory.UpdateSourceFile(file, tx.factory.NewNodeList(statements)) + visited = tx.Factory().UpdateSourceFile(file, tx.Factory().NewNodeList(statements)) } tx.currentSourceFile = nil @@ -312,13 +313,13 @@ func (tx *JSXTransformer) convertJsxChildrenToChildrenPropObject(children []*ast if prop == nil { return nil } - return tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{prop}), false) + return tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{prop}), false) } func (tx *JSXTransformer) transformJsxChildToExpression(node *ast.Node) *ast.Node { tx.setInChild(true) defer tx.setInChild(false) - return tx.visitor.Visit(node) + return tx.Visitor().Visit(node) } func (tx *JSXTransformer) convertJsxChildrenToChildrenPropAssignment(children []*ast.JsxChild) *ast.Node { @@ -328,7 +329,7 @@ func (tx *JSXTransformer) convertJsxChildrenToChildrenPropAssignment(children [] if result == nil { return nil } - return tx.factory.NewPropertyAssignment(nil, tx.factory.NewIdentifier("children"), nil, nil, result) + return tx.Factory().NewPropertyAssignment(nil, tx.Factory().NewIdentifier("children"), nil, nil, result) } results := make([]*ast.Node, 0, len(nonWhitespceChildren)) for _, child := range nonWhitespceChildren { @@ -341,7 +342,7 @@ func (tx *JSXTransformer) convertJsxChildrenToChildrenPropAssignment(children [] if len(results) == 0 { return nil } - return tx.factory.NewPropertyAssignment(nil, tx.factory.NewIdentifier("children"), nil, nil, tx.factory.NewArrayLiteralExpression(tx.factory.NewNodeList(results), false)) + return tx.Factory().NewPropertyAssignment(nil, tx.Factory().NewIdentifier("children"), nil, nil, tx.Factory().NewArrayLiteralExpression(tx.Factory().NewNodeList(results), false)) } func (tx *JSXTransformer) getTagName(node *ast.Node) *ast.Node { @@ -350,11 +351,11 @@ func (tx *JSXTransformer) getTagName(node *ast.Node) *ast.Node { } else if ast.IsJsxOpeningLikeElement(node) { tagName := node.TagName() if ast.IsIdentifier(tagName) && scanner.IsIntrinsicJsxName(tagName.Text()) { - return tx.factory.NewStringLiteral(tagName.Text()) + return tx.Factory().NewStringLiteral(tagName.Text()) } else if ast.IsJsxNamespacedName(tagName) { - return tx.factory.NewStringLiteral(tagName.AsJsxNamespacedName().Namespace.Text() + ":" + tagName.AsJsxNamespacedName().Name().Text()) + return tx.Factory().NewStringLiteral(tagName.AsJsxNamespacedName().Namespace.Text() + ":" + tagName.AsJsxNamespacedName().Name().Text()) } else { - return createExpressionFromEntityName(tx.factory, tagName) + return createExpressionFromEntityName(tx.Factory(), tagName) } } else { panic("unhandled node kind passed to getTagName: " + node.Kind.String()) @@ -385,7 +386,7 @@ func (tx *JSXTransformer) visitJsxOpeningLikeElementJSX(element *ast.Node, child if childrenProp != nil { objectChildren = append(objectChildren, childrenProp) } - object = tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList(objectChildren), false) // When there are no attributes, React wants {} + object = tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList(objectChildren), false) // When there are no attributes, React wants {} } return tx.visitJsxOpeningLikeElementOrFragmentJSX( tagName, @@ -400,7 +401,7 @@ func (tx *JSXTransformer) transformJsxAttributesToObjectProps(attrs []*ast.Node, target := tx.compilerOptions.GetEmitScriptTarget() if target != core.ScriptTargetNone && target >= core.ScriptTargetES2018 { // target has object spreads, can keep as-is - return tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList(tx.transformJsxAttributesToProps(attrs, childrenProp)), false) + return tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList(tx.transformJsxAttributesToProps(attrs, childrenProp)), false) } return tx.transformJsxAttributesToExpression(attrs, childrenProp) } @@ -417,15 +418,15 @@ func (tx *JSXTransformer) transformJsxAttributesToExpression(attrs []*ast.Node, for _, prop := range attr.Expression().Properties() { if ast.IsSpreadAssignment(prop) { expressions, properties = tx.combinePropertiesIntoNewExpression(expressions, properties) - expressions = append(expressions, tx.visitor.Visit(prop.Expression())) + expressions = append(expressions, tx.Visitor().Visit(prop.Expression())) continue } - properties = append(properties, tx.visitor.Visit(prop)) + properties = append(properties, tx.Visitor().Visit(prop)) } continue } expressions, properties = tx.combinePropertiesIntoNewExpression(expressions, properties) - expressions = append(expressions, tx.visitor.Visit(attr.Expression())) + expressions = append(expressions, tx.Visitor().Visit(attr.Expression())) continue } properties = append(properties, tx.transformJsxAttributeToObjectLiteralElement(attr.AsJsxAttribute())) @@ -441,20 +442,20 @@ func (tx *JSXTransformer) transformJsxAttributesToExpression(attrs []*ast.Node, // We must always emit at least one object literal before a spread attribute // as the JSX always factory expects a fresh object, so we need to make a copy here // we also avoid mutating an external reference by doing this (first expression is used as assign's target) - expressions = append([]*ast.Expression{tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{}), false)}, expressions...) + expressions = append([]*ast.Expression{tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{}), false)}, expressions...) } if len(expressions) == 1 { return expressions[0] } - return tx.factory.NewAssignHelper(expressions, tx.compilerOptions.GetEmitScriptTarget()) + return tx.Factory().NewAssignHelper(expressions, tx.compilerOptions.GetEmitScriptTarget()) } func (tx *JSXTransformer) combinePropertiesIntoNewExpression(expressions []*ast.Expression, props []*ast.ObjectLiteralElement) ([]*ast.Expression, []*ast.ObjectLiteralElement) { if len(props) == 0 { return expressions, props } - newObj := tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList(props), false) + newObj := tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList(props), false) expressions = append(expressions, newObj) return expressions, nil } @@ -486,16 +487,16 @@ func hasProto(obj *ast.ObjectLiteralExpression) bool { func (tx *JSXTransformer) transformJsxSpreadAttributesToProps(node *ast.JsxSpreadAttribute) []*ast.Node { if ast.IsObjectLiteralExpression(node.Expression) && !hasProto(node.Expression.AsObjectLiteralExpression()) { - res, _ := tx.visitor.VisitSlice(node.Expression.Properties()) + res, _ := tx.Visitor().VisitSlice(node.Expression.Properties()) return res } - return []*ast.Node{tx.factory.NewSpreadAssignment(tx.visitor.Visit(node.Expression))} + return []*ast.Node{tx.Factory().NewSpreadAssignment(tx.Visitor().Visit(node.Expression))} } func (tx *JSXTransformer) transformJsxAttributeToObjectLiteralElement(node *ast.JsxAttribute) *ast.Node { name := tx.getAttributeName(node) expression := tx.transformJsxAttributeInitializer(node.Initializer) - return tx.factory.NewPropertyAssignment(nil, name, nil, nil, expression) + return tx.Factory().NewPropertyAssignment(nil, name, nil, nil, expression) } /** @@ -510,32 +511,32 @@ func (tx *JSXTransformer) getAttributeName(node *ast.JsxAttribute) *ast.Node { if scanner.IsIdentifierText(text, core.LanguageVariantStandard) { return name } - return tx.factory.NewStringLiteral(text) + return tx.Factory().NewStringLiteral(text) } // must be jsx namespace - return tx.factory.NewStringLiteral(name.AsJsxNamespacedName().Namespace.Text() + ":" + name.AsJsxNamespacedName().Name().Text()) + return tx.Factory().NewStringLiteral(name.AsJsxNamespacedName().Namespace.Text() + ":" + name.AsJsxNamespacedName().Name().Text()) } func (tx *JSXTransformer) transformJsxAttributeInitializer(node *ast.Node) *ast.Node { if node == nil { - return tx.factory.NewTrueExpression() + return tx.Factory().NewTrueExpression() } if node.Kind == ast.KindStringLiteral { // Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which // Need to be escaped to be handled correctly in a normal string - res := tx.factory.NewStringLiteral(decodeEntities(node.Text())) + res := tx.Factory().NewStringLiteral(decodeEntities(node.Text())) res.Loc = node.Loc return res } if node.Kind == ast.KindJsxExpression { if node.AsJsxExpression().Expression == nil { - return tx.factory.NewTrueExpression() + return tx.Factory().NewTrueExpression() } - return tx.visitor.Visit(node.AsJsxExpression().Expression) + return tx.Visitor().Visit(node.AsJsxExpression().Expression) } if ast.IsJsxElement(node) || ast.IsJsxSelfClosingElement(node) || ast.IsJsxFragment(node) { tx.setInChild(false) - return tx.visitor.Visit(node) + return tx.Visitor().Visit(node) } panic("Unhandled node kind found in jsx initializer: " + node.Kind.String()) } @@ -561,35 +562,35 @@ func (tx *JSXTransformer) visitJsxOpeningLikeElementOrFragmentJSX( } if tx.compilerOptions.Jsx == core.JsxEmitReactJSXDev { - originalFile := tx.emitContext.Original(tx.currentSourceFile.AsNode()) + originalFile := tx.EmitContext().Original(tx.currentSourceFile.AsNode()) if originalFile != nil && ast.IsSourceFile(originalFile) { // "maybeKey" has to be replaced with "void 0" to not break the jsxDEV signature if keyAttr == nil { - args = append(args, tx.factory.NewVoidZeroExpression()) + args = append(args, tx.Factory().NewVoidZeroExpression()) } // isStaticChildren development flag if isStaticChildren { - args = append(args, tx.factory.NewTrueExpression()) + args = append(args, tx.Factory().NewTrueExpression()) } else { - args = append(args, tx.factory.NewFalseExpression()) + args = append(args, tx.Factory().NewFalseExpression()) } // __source development flag line, col := scanner.GetLineAndCharacterOfPosition(originalFile.AsSourceFile(), location.Pos()) - args = append(args, tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewPropertyAssignment(nil, tx.factory.NewIdentifier("fileName"), nil, nil, tx.getCurrentFileNameExpression()), - tx.factory.NewPropertyAssignment(nil, tx.factory.NewIdentifier("lineNumber"), nil, nil, tx.factory.NewNumericLiteral(strconv.FormatInt(int64(line+1), 10))), - tx.factory.NewPropertyAssignment(nil, tx.factory.NewIdentifier("columnNumber"), nil, nil, tx.factory.NewNumericLiteral(strconv.FormatInt(int64(col+1), 10))), + args = append(args, tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewPropertyAssignment(nil, tx.Factory().NewIdentifier("fileName"), nil, nil, tx.getCurrentFileNameExpression()), + tx.Factory().NewPropertyAssignment(nil, tx.Factory().NewIdentifier("lineNumber"), nil, nil, tx.Factory().NewNumericLiteral(strconv.FormatInt(int64(line+1), 10))), + tx.Factory().NewPropertyAssignment(nil, tx.Factory().NewIdentifier("columnNumber"), nil, nil, tx.Factory().NewNumericLiteral(strconv.FormatInt(int64(col+1), 10))), }), false)) // __self development flag - args = append(args, tx.factory.NewThisExpression()) + args = append(args, tx.Factory().NewThisExpression()) } } - element := tx.factory.NewCallExpression(tx.getJsxFactoryCallee(isStaticChildren), nil, nil, tx.factory.NewNodeList(args), ast.NodeFlagsNone) + element := tx.Factory().NewCallExpression(tx.getJsxFactoryCallee(isStaticChildren), nil, nil, tx.Factory().NewNodeList(args), ast.NodeFlagsNone) element.Loc = location.Loc if tx.inJsxChild { - tx.emitContext.AddEmitFlags(element, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(element, printer.EFStartOnNewLine) } return element @@ -604,7 +605,7 @@ func (tx *JSXTransformer) visitJsxOpeningFragmentJSX(fragment *ast.JsxOpeningFra } } if childrenProps == nil { - childrenProps = tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{}), false) + childrenProps = tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{}), false) } return tx.visitJsxOpeningLikeElementOrFragmentJSX( tx.getImplicitJsxFragmentReference(), @@ -623,20 +624,20 @@ func (tx *JSXTransformer) createReactNamespace(reactNamespace string, parent *as if len(reactNamespace) == 0 { reactNamespace = "React" } - react := tx.factory.NewIdentifier(reactNamespace) + react := tx.Factory().NewIdentifier(reactNamespace) react.Flags &= ^ast.NodeFlagsSynthesized // Set the parent that is in parse tree // this makes sure that parent chain is intact for checker to traverse complete scope tree - react.Parent = tx.emitContext.ParseNode(parent) + react.Parent = tx.EmitContext().ParseNode(parent) return react } func (tx *JSXTransformer) createJsxFactoryExpressionFromEntityName(e *ast.Node, parent *ast.Node) *ast.Node { if ast.IsQualifiedName(e) { left := tx.createJsxFactoryExpressionFromEntityName(e.AsQualifiedName().Left, parent) - right := tx.factory.NewIdentifier(e.AsQualifiedName().Right.Text()) - return tx.factory.NewPropertyAccessExpression(left, nil, right, ast.NodeFlagsNone) + right := tx.Factory().NewIdentifier(e.AsQualifiedName().Right.Text()) + return tx.Factory().NewPropertyAccessExpression(left, nil, right, ast.NodeFlagsNone) } return tx.createReactNamespace(e.AsIdentifier().Text, parent) } @@ -645,10 +646,10 @@ func (tx *JSXTransformer) createJsxPsuedoFactoryExpression(parent *ast.Node, e * if e != nil { return tx.createJsxFactoryExpressionFromEntityName(e, parent) } - return tx.factory.NewPropertyAccessExpression( + return tx.Factory().NewPropertyAccessExpression( tx.createReactNamespace(tx.compilerOptions.ReactNamespace, parent), nil, - tx.factory.NewIdentifier(target), + tx.Factory().NewIdentifier(target), ast.NodeFlagsNone, ) } @@ -670,7 +671,7 @@ func (tx *JSXTransformer) visitJsxOpeningLikeElementCreateElement(element *ast.N if len(attrs) > 0 { objectProperties = tx.transformJsxAttributesToObjectProps(attrs, nil) } else { - objectProperties = tx.factory.NewKeywordExpression(ast.KindNullKeyword) // When there are no attributes, React wants "null" + objectProperties = tx.Factory().NewKeywordExpression(ast.KindNullKeyword) // When there are no attributes, React wants "null" } var callee *ast.Expression @@ -686,7 +687,7 @@ func (tx *JSXTransformer) visitJsxOpeningLikeElementCreateElement(element *ast.N res := tx.transformJsxChildToExpression(c) if res != nil { if len(children.Nodes) > 1 { - tx.emitContext.AddEmitFlags(res, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(res, printer.EFStartOnNewLine) } newChildren = append(newChildren, res) } @@ -698,17 +699,17 @@ func (tx *JSXTransformer) visitJsxOpeningLikeElementCreateElement(element *ast.N args = append(args, objectProperties) args = append(args, newChildren...) - result := tx.factory.NewCallExpression( + result := tx.Factory().NewCallExpression( callee, nil, nil, - tx.factory.NewNodeList(args), + tx.Factory().NewNodeList(args), ast.NodeFlagsNone, ) result.Loc = location.Loc if tx.inJsxChild { - tx.emitContext.AddEmitFlags(result, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(result, printer.EFStartOnNewLine) } return result } @@ -723,7 +724,7 @@ func (tx *JSXTransformer) visitJsxOpeningFragmentCreateElement(fragment *ast.Jsx res := tx.transformJsxChildToExpression(c) if res != nil { if len(children.Nodes) > 1 { - tx.emitContext.AddEmitFlags(res, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(res, printer.EFStartOnNewLine) } newChildren = append(newChildren, res) } @@ -732,20 +733,20 @@ func (tx *JSXTransformer) visitJsxOpeningFragmentCreateElement(fragment *ast.Jsx args := make([]*ast.Expression, 0, len(newChildren)+2) args = append(args, tagName) - args = append(args, tx.factory.NewKeywordExpression(ast.KindNullKeyword)) + args = append(args, tx.Factory().NewKeywordExpression(ast.KindNullKeyword)) args = append(args, newChildren...) - result := tx.factory.NewCallExpression( + result := tx.Factory().NewCallExpression( callee, nil, nil, - tx.factory.NewNodeList(args), + tx.Factory().NewNodeList(args), ast.NodeFlagsNone, ) result.Loc = location.Loc if tx.inJsxChild { - tx.emitContext.AddEmitFlags(result, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(result, printer.EFStartOnNewLine) } return result } @@ -755,7 +756,7 @@ func (tx *JSXTransformer) visitJsxText(text *ast.JsxText) *ast.Node { if len(fixed) == 0 { return nil } - return tx.factory.NewStringLiteral(fixed) + return tx.Factory().NewStringLiteral(fixed) } func addLineOfJsxText(b *strings.Builder, trimmedLine string, isInitial bool) { @@ -826,9 +827,9 @@ func fixupWhitespaceAndDecodeEntities(text string) string { } func (tx *JSXTransformer) visitJsxExpression(expression *ast.JsxExpression) *ast.Node { - e := tx.visitor.Visit(expression.Expression) + e := tx.Visitor().Visit(expression.Expression) if expression.DotDotDotToken != nil { - return tx.factory.NewSpreadElement(e) + return tx.Factory().NewSpreadElement(e) } return e } diff --git a/internal/transformers/jsxtransforms/utilities.go b/internal/transformers/jsxtransforms/utilities.go new file mode 100644 index 0000000000..5909b552bc --- /dev/null +++ b/internal/transformers/jsxtransforms/utilities.go @@ -0,0 +1,20 @@ +package jsxtransforms + +import "github.com/microsoft/typescript-go/internal/ast" + +func createExpressionFromEntityName(factory ast.NodeFactoryCoercible, node *ast.Node) *ast.Expression { + if ast.IsQualifiedName(node) { + left := createExpressionFromEntityName(factory, node.AsQualifiedName().Left) + // TODO(rbuckton): Does this need to be parented? + right := node.AsQualifiedName().Right.Clone(factory.AsNodeFactory()) + right.Loc = node.AsQualifiedName().Right.Loc + right.Parent = node.AsQualifiedName().Right.Parent + return factory.AsNodeFactory().NewPropertyAccessExpression(left, nil, right, ast.NodeFlagsNone) + } else { + // TODO(rbuckton): Does this need to be parented? + res := node.Clone(factory.AsNodeFactory()) + res.Loc = node.Loc + res.Parent = node.Parent + return res + } +} diff --git a/internal/transformers/modifiervisitor.go b/internal/transformers/modifiervisitor.go index 78b5fa80ff..11c50b19d5 100644 --- a/internal/transformers/modifiervisitor.go +++ b/internal/transformers/modifiervisitor.go @@ -18,7 +18,7 @@ func (v *modifierVisitor) visit(node *ast.Node) *ast.Node { return node } -func extractModifiers(emitContext *printer.EmitContext, modifiers *ast.ModifierList, allowed ast.ModifierFlags) *ast.ModifierList { +func ExtractModifiers(emitContext *printer.EmitContext, modifiers *ast.ModifierList, allowed ast.ModifierFlags) *ast.ModifierList { if modifiers == nil { return nil } diff --git a/internal/transformers/commonjsmodule.go b/internal/transformers/moduletransforms/commonjsmodule.go similarity index 72% rename from internal/transformers/commonjsmodule.go rename to internal/transformers/moduletransforms/commonjsmodule.go index e00ada3069..02e5458277 100644 --- a/internal/transformers/commonjsmodule.go +++ b/internal/transformers/moduletransforms/commonjsmodule.go @@ -1,4 +1,4 @@ -package transformers +package moduletransforms import ( "slices" @@ -8,11 +8,12 @@ import ( "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" "github.com/microsoft/typescript-go/internal/tspath" ) type CommonJSModuleTransformer struct { - Transformer + transformers.Transformer topLevelVisitor *ast.NodeVisitor // visits statements at top level of a module topLevelNestedVisitor *ast.NodeVisitor // visits nested statements at top level of a module discardedValueVisitor *ast.NodeVisitor // visits expressions whose values would be discarded at runtime @@ -28,7 +29,7 @@ type CommonJSModuleTransformer struct { currentNode *ast.Node // used for ancestor tracking via pushNode/popNode to detect expression identifiers } -func NewCommonJSModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *Transformer { +func NewCommonJSModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *transformers.Transformer { if resolver == nil { resolver = binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{}) } @@ -172,7 +173,7 @@ func (tx *CommonJSModuleTransformer) visitNoStack(node *ast.Node, resultIsDiscar case ast.KindIdentifier: node = tx.visitIdentifier(node) default: - node = tx.visitor.VisitEachChild(node) + node = tx.Visitor().VisitEachChild(node) } return node @@ -234,7 +235,7 @@ func (tx *CommonJSModuleTransformer) visitSourceFile(node *ast.SourceFile) *ast. } tx.currentSourceFile = node - tx.currentModuleInfo = collectExternalModuleInfo(node, tx.compilerOptions, tx.emitContext, tx.resolver) + tx.currentModuleInfo = collectExternalModuleInfo(node, tx.compilerOptions, tx.EmitContext(), tx.resolver) updated := tx.transformCommonJSModule(node) tx.currentSourceFile = nil tx.currentModuleInfo = nil @@ -254,27 +255,27 @@ func (tx *CommonJSModuleTransformer) shouldEmitUnderscoreUnderscoreESModule() bo } func (tx *CommonJSModuleTransformer) createUnderscoreUnderscoreESModule() *ast.Statement { - statement := tx.factory.NewExpressionStatement( - tx.factory.NewCallExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("Object"), + statement := tx.Factory().NewExpressionStatement( + tx.Factory().NewCallExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("Object"), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("defineProperty"), + tx.Factory().NewIdentifier("defineProperty"), ast.NodeFlagsNone, ), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewIdentifier("exports"), - tx.factory.NewStringLiteral("__esModule"), - tx.factory.NewObjectLiteralExpression( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewPropertyAssignment( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewIdentifier("exports"), + tx.Factory().NewStringLiteral("__esModule"), + tx.Factory().NewObjectLiteralExpression( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewPropertyAssignment( nil, /*modifiers*/ - tx.factory.NewIdentifier("value"), + tx.Factory().NewIdentifier("value"), nil, /*postfixToken*/ nil, /*typeNode*/ - tx.factory.NewTrueExpression(), + tx.Factory().NewTrueExpression(), ), }), false, /*multiLine*/ @@ -283,25 +284,25 @@ func (tx *CommonJSModuleTransformer) createUnderscoreUnderscoreESModule() *ast.S ast.NodeFlagsNone, ), ) - tx.emitContext.SetEmitFlags(statement, printer.EFCustomPrologue) + tx.EmitContext().SetEmitFlags(statement, printer.EFCustomPrologue) return statement } func (tx *CommonJSModuleTransformer) transformCommonJSModule(node *ast.SourceFile) *ast.Node { - tx.emitContext.StartVariableEnvironment() + tx.EmitContext().StartVariableEnvironment() // emit standard prologue directives (e.g. "use strict") - prologue, rest := tx.factory.SplitStandardPrologue(node.Statements.Nodes) + prologue, rest := tx.Factory().SplitStandardPrologue(node.Statements.Nodes) statements := slices.Clone(prologue) // ensure "use strict" if not present if ast.IsExternalModule(tx.currentSourceFile) || tx.compilerOptions.AlwaysStrict.DefaultIfUnknown(tx.compilerOptions.Strict).IsTrue() { - statements = tx.factory.EnsureUseStrict(statements) + statements = tx.Factory().EnsureUseStrict(statements) } // emit custom prologues from other transformations - custom, rest := tx.factory.SplitCustomPrologue(rest) + custom, rest := tx.Factory().SplitCustomPrologue(rest) statements = append(statements, core.FirstResult(tx.topLevelVisitor.VisitSlice(custom))...) // emits `Object.defineProperty(exports, "__esModule", { value: true });` at the top of the file @@ -315,30 +316,30 @@ func (tx *CommonJSModuleTransformer) transformCommonJSModule(node *ast.SourceFil const chunkSize = 50 l := len(tx.currentModuleInfo.exportedNames) for i := 0; i < l; i += chunkSize { - right := tx.factory.NewVoidZeroExpression() + right := tx.Factory().NewVoidZeroExpression() for _, nextId := range tx.currentModuleInfo.exportedNames[i:min(i+chunkSize, l)] { var left *ast.Expression if nextId.Kind == ast.KindStringLiteral { - left = tx.factory.NewElementAccessExpression( - tx.factory.NewIdentifier("exports"), + left = tx.Factory().NewElementAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ - tx.factory.NewStringLiteralFromNode(nextId), + tx.Factory().NewStringLiteralFromNode(nextId), ast.NodeFlagsNone, ) } else { - name := nextId.Clone(tx.factory) - tx.emitContext.SetEmitFlags(name, printer.EFNoSourceMap) // TODO: Strada emits comments here, but shouldn't - left = tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("exports"), + name := nextId.Clone(tx.Factory()) + tx.EmitContext().SetEmitFlags(name, printer.EFNoSourceMap) // TODO: Strada emits comments here, but shouldn't + left = tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ name, ast.NodeFlagsNone, ) } - right = tx.factory.NewAssignmentExpression(left, right) + right = tx.Factory().NewAssignmentExpression(left, right) } - statement := tx.factory.NewExpressionStatement(right) - tx.emitContext.AddEmitFlags(statement, printer.EFCustomPrologue) + statement := tx.Factory().NewExpressionStatement(right) + tx.EmitContext().AddEmitFlags(statement, printer.EFCustomPrologue) statements = append(statements, statement) } } @@ -358,24 +359,24 @@ func (tx *CommonJSModuleTransformer) transformCommonJSModule(node *ast.SourceFil statements = tx.appendExportEqualsIfNeeded(statements) // merge temp variables into the statement list - statements = tx.emitContext.EndAndMergeVariableEnvironment(statements) + statements = tx.EmitContext().EndAndMergeVariableEnvironment(statements) - statementList := tx.factory.NewNodeList(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = node.Statements.Loc - result := tx.factory.UpdateSourceFile(node, statementList).AsSourceFile() - tx.emitContext.AddEmitHelper(result.AsNode(), tx.emitContext.ReadEmitHelpers()...) + result := tx.Factory().UpdateSourceFile(node, statementList).AsSourceFile() + tx.EmitContext().AddEmitHelper(result.AsNode(), tx.EmitContext().ReadEmitHelpers()...) - externalHelpersImportDeclaration := createExternalHelpersImportDeclarationIfNeeded(tx.emitContext, result, tx.compilerOptions, tx.getEmitModuleFormatOfFile(node), false /*hasExportStarsToExportValues*/, false /*hasImportStar*/, false /*hasImportDefault*/) + externalHelpersImportDeclaration := createExternalHelpersImportDeclarationIfNeeded(tx.EmitContext(), result, tx.compilerOptions, tx.getEmitModuleFormatOfFile(node), false /*hasExportStarsToExportValues*/, false /*hasImportStar*/, false /*hasImportDefault*/) if externalHelpersImportDeclaration != nil { - prologue, rest := tx.factory.SplitStandardPrologue(result.Statements.Nodes) - custom, rest := tx.factory.SplitCustomPrologue(rest) + prologue, rest := tx.Factory().SplitStandardPrologue(result.Statements.Nodes) + custom, rest := tx.Factory().SplitCustomPrologue(rest) statements := slices.Clone(prologue) statements = append(statements, custom...) statements = append(statements, tx.topLevelVisitor.VisitNode(externalHelpersImportDeclaration)) statements = append(statements, rest...) - statementList := tx.factory.NewNodeList(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = result.Statements.Loc - result = tx.factory.UpdateSourceFile(result, statementList).AsSourceFile() + result = tx.Factory().UpdateSourceFile(result, statementList).AsSourceFile() } return result.AsNode() @@ -386,22 +387,22 @@ func (tx *CommonJSModuleTransformer) transformCommonJSModule(node *ast.SourceFil // - The `statements` parameter is a statement list to which the down-level export statements are to be appended. func (tx *CommonJSModuleTransformer) appendExportEqualsIfNeeded(statements []*ast.Statement) []*ast.Statement { if tx.currentModuleInfo.exportEquals != nil { - expressionResult := tx.visitor.VisitNode(tx.currentModuleInfo.exportEquals.Expression) + expressionResult := tx.Visitor().VisitNode(tx.currentModuleInfo.exportEquals.Expression) if expressionResult != nil { - statement := tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("module"), + statement := tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("module"), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("exports"), + tx.Factory().NewIdentifier("exports"), ast.NodeFlagsNone, ), expressionResult, ), ) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, tx.currentModuleInfo.exportEquals.AsNode()) - tx.emitContext.AddEmitFlags(statement, printer.EFNoComments) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, tx.currentModuleInfo.exportEquals.AsNode()) + tx.EmitContext().AddEmitFlags(statement, printer.EFNoComments) statements = append(statements, statement) } } @@ -483,7 +484,7 @@ func (tx *CommonJSModuleTransformer) appendExportsOfBindingElement(statements [] statements = tx.appendExportsOfBindingElement(statements, element, isForInOrOfInitializer) } } - } else if !isGeneratedIdentifier(tx.emitContext, decl.Name()) && + } else if !transformers.IsGeneratedIdentifier(tx.EmitContext(), decl.Name()) && (!ast.IsVariableDeclaration(decl) || decl.Initializer() != nil || isForInOrOfInitializer) { statements = tx.appendExportsOfDeclaration(statements, decl, nil /*seen*/, false /*liveBinding*/) } @@ -504,12 +505,12 @@ func (tx *CommonJSModuleTransformer) appendExportsOfClassOrFunctionDeclaration(s if ast.HasSyntacticModifier(decl, ast.ModifierFlagsExport) { var exportName *ast.IdentifierNode if ast.HasSyntacticModifier(decl, ast.ModifierFlagsDefault) { - exportName = tx.factory.NewIdentifier("default") + exportName = tx.Factory().NewIdentifier("default") } else { - exportName = tx.factory.GetDeclarationName(decl) + exportName = tx.Factory().GetDeclarationName(decl) } - exportValue := tx.factory.GetLocalName(decl) + exportValue := tx.Factory().GetLocalName(decl) statements = tx.appendExportStatement(statements, seen, exportName, exportValue, &decl.Loc, false /*allowComments*/, false /*liveBinding*/) } @@ -534,7 +535,7 @@ func (tx *CommonJSModuleTransformer) appendExportsOfDeclaration(statements []*as } if name := decl.Name(); tx.currentModuleInfo.exportSpecifiers.Len() > 0 && name != nil && ast.IsIdentifier(name) { - name = tx.factory.GetDeclarationName(decl) + name = tx.Factory().GetDeclarationName(decl) exportSpecifiers := tx.currentModuleInfo.exportSpecifiers.Get(name.Text()) if len(exportSpecifiers) > 0 { exportValue := tx.visitExpressionIdentifier(name) @@ -572,13 +573,13 @@ func (tx *CommonJSModuleTransformer) appendExportStatement(statements []*ast.Sta // - The `location` parameter is the location to use for source maps and comments for the export. // - The `allowComments` parameter indicates whether to emit comments for the statement. func (tx *CommonJSModuleTransformer) createExportStatement(name *ast.ModuleExportName, value *ast.Expression, location *core.TextRange, allowComments bool, liveBinding bool) *ast.Statement { - statement := tx.factory.NewExpressionStatement(tx.createExportExpression(name, value, nil /*location*/, liveBinding)) + statement := tx.Factory().NewExpressionStatement(tx.createExportExpression(name, value, nil /*location*/, liveBinding)) if location != nil { - tx.emitContext.SetCommentRange(statement, *location) + tx.EmitContext().SetCommentRange(statement, *location) } - tx.emitContext.AddEmitFlags(statement, printer.EFStartOnNewLine) + tx.EmitContext().AddEmitFlags(statement, printer.EFStartOnNewLine) if !allowComments { - tx.emitContext.AddEmitFlags(statement, printer.EFNoComments) + tx.EmitContext().AddEmitFlags(statement, printer.EFNoComments) } return statement } @@ -593,42 +594,42 @@ func (tx *CommonJSModuleTransformer) createExportExpression(name *ast.ModuleExpo if liveBinding { // For a live binding we emit a getter on `exports` that returns the value: // Object.defineProperty(exports, "", { enumerable: true, get: function () { return ; } }); - expression = tx.factory.NewCallExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("Object"), + expression = tx.Factory().NewCallExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("Object"), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("defineProperty"), + tx.Factory().NewIdentifier("defineProperty"), ast.NodeFlagsNone, ), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewIdentifier("exports"), - tx.factory.NewStringLiteralFromNode(name), - tx.factory.NewObjectLiteralExpression( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewPropertyAssignment( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewIdentifier("exports"), + tx.Factory().NewStringLiteralFromNode(name), + tx.Factory().NewObjectLiteralExpression( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewPropertyAssignment( nil, /*modifiers*/ - tx.factory.NewIdentifier("enumerable"), + tx.Factory().NewIdentifier("enumerable"), nil, /*postfixToken*/ nil, /*typeNode*/ - tx.factory.NewTrueExpression(), + tx.Factory().NewTrueExpression(), ), - tx.factory.NewPropertyAssignment( + tx.Factory().NewPropertyAssignment( nil, /*modifiers*/ - tx.factory.NewIdentifier("get"), + tx.Factory().NewIdentifier("get"), nil, /*postfixToken*/ nil, /*typeNode*/ - tx.factory.NewFunctionExpression( + tx.Factory().NewFunctionExpression( nil, /*modifiers*/ nil, /*asteriskToken*/ nil, /*name*/ nil, /*typeParameters*/ - tx.factory.NewNodeList([]*ast.Node{}), + tx.Factory().NewNodeList([]*ast.Node{}), nil, /*type*/ - tx.factory.NewBlock( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewReturnStatement(value), + tx.Factory().NewBlock( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewReturnStatement(value), }), false, /*multiLine*/ ), @@ -646,26 +647,26 @@ func (tx *CommonJSModuleTransformer) createExportExpression(name *ast.ModuleExpo if name.Kind == ast.KindStringLiteral { // emits: // exports[""] = ; - left = tx.factory.NewElementAccessExpression( - tx.factory.NewIdentifier("exports"), + left = tx.Factory().NewElementAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ - tx.factory.NewStringLiteralFromNode(name), + tx.Factory().NewStringLiteralFromNode(name), ast.NodeFlagsNone, ) } else { // emits: // exports. = ; - left = tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("exports"), + left = tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ - name.Clone(tx.factory), + name.Clone(tx.Factory()), ast.NodeFlagsNone, ) } - expression = tx.factory.NewAssignmentExpression(left, value) + expression = tx.Factory().NewAssignmentExpression(left, value) } if location != nil { - tx.emitContext.SetCommentRange(expression, *location) + tx.EmitContext().SetCommentRange(expression, *location) } return expression } @@ -673,37 +674,37 @@ func (tx *CommonJSModuleTransformer) createExportExpression(name *ast.ModuleExpo // Creates a `require()` call to import an external module. func (tx *CommonJSModuleTransformer) createRequireCall(node *ast.Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) *ast.Node { var args []*ast.Expression - moduleName := getExternalModuleNameLiteral(tx.factory, node, tx.currentSourceFile, nil /*host*/, nil /*resolver*/, tx.compilerOptions) + moduleName := getExternalModuleNameLiteral(tx.Factory(), node, tx.currentSourceFile, nil /*host*/, nil /*resolver*/, tx.compilerOptions) if moduleName != nil { - args = append(args, rewriteModuleSpecifier(tx.emitContext, moduleName, tx.compilerOptions)) + args = append(args, rewriteModuleSpecifier(tx.EmitContext(), moduleName, tx.compilerOptions)) } - return tx.factory.NewCallExpression( - tx.factory.NewIdentifier("require"), + return tx.Factory().NewCallExpression( + tx.Factory().NewIdentifier("require"), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList(args), + tx.Factory().NewNodeList(args), ast.NodeFlagsNone) } func (tx *CommonJSModuleTransformer) getHelperExpressionForExport(node *ast.ExportDeclaration, innerExpr *ast.Expression) *ast.Expression { - if !tx.compilerOptions.GetESModuleInterop() || tx.emitContext.EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper != 0 { + if !tx.compilerOptions.GetESModuleInterop() || tx.EmitContext().EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper != 0 { return innerExpr } if getExportNeedsImportStarHelper(node) { - return tx.visitor.VisitNode(tx.factory.NewImportStarHelper(innerExpr)) + return tx.Visitor().VisitNode(tx.Factory().NewImportStarHelper(innerExpr)) } return innerExpr } func (tx *CommonJSModuleTransformer) getHelperExpressionForImport(node *ast.ImportDeclaration, innerExpr *ast.Expression) *ast.Expression { - if !tx.compilerOptions.GetESModuleInterop() || tx.emitContext.EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper != 0 { + if !tx.compilerOptions.GetESModuleInterop() || tx.EmitContext().EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper != 0 { return innerExpr } if getImportNeedsImportStarHelper(node) { - return tx.visitor.VisitNode(tx.factory.NewImportStarHelper(innerExpr)) + return tx.Visitor().VisitNode(tx.Factory().NewImportStarHelper(innerExpr)) } if getImportNeedsImportDefaultHelper(node) { - return tx.visitor.VisitNode(tx.factory.NewImportDefaultHelper(innerExpr)) + return tx.Visitor().VisitNode(tx.Factory().NewImportDefaultHelper(innerExpr)) } return innerExpr } @@ -711,9 +712,9 @@ func (tx *CommonJSModuleTransformer) getHelperExpressionForImport(node *ast.Impo func (tx *CommonJSModuleTransformer) visitTopLevelImportDeclaration(node *ast.ImportDeclaration) *ast.Node { if node.ImportClause == nil { // import "mod"; - statement := tx.factory.NewExpressionStatement(tx.createRequireCall(node.AsNode())) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + statement := tx.Factory().NewExpressionStatement(tx.createRequireCall(node.AsNode())) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) return statement } @@ -723,8 +724,8 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportDeclaration(node *ast.Im if namespaceDeclaration != nil && !ast.IsDefaultImport(node.AsNode()) { // import * as n from "mod"; variables = append(variables, - tx.factory.NewVariableDeclaration( - namespaceDeclaration.Name().Clone(tx.factory), + tx.Factory().NewVariableDeclaration( + namespaceDeclaration.Name().Clone(tx.Factory()), nil, /*exclamationToken*/ nil, /*type*/ tx.getHelperExpressionForImport(node, tx.createRequireCall(node.AsNode())), @@ -736,8 +737,8 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportDeclaration(node *ast.Im // import d, { x, y } from "mod"; // import d, * as n from "mod"; variables = append(variables, - tx.factory.NewVariableDeclaration( - tx.factory.NewGeneratedNameForNode(node.AsNode()), + tx.Factory().NewVariableDeclaration( + tx.Factory().NewGeneratedNameForNode(node.AsNode()), nil, /*exclamationToken*/ nil, /*type*/ tx.getHelperExpressionForImport(node, tx.createRequireCall(node.AsNode())), @@ -746,29 +747,29 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportDeclaration(node *ast.Im if namespaceDeclaration != nil && ast.IsDefaultImport(node.AsNode()) { variables = append(variables, - tx.factory.NewVariableDeclaration( - namespaceDeclaration.Name().Clone(tx.factory), + tx.Factory().NewVariableDeclaration( + namespaceDeclaration.Name().Clone(tx.Factory()), nil, /*exclamationToken*/ nil, /*type*/ - tx.factory.NewGeneratedNameForNode(node.AsNode()), + tx.Factory().NewGeneratedNameForNode(node.AsNode()), ), ) } } - varStatement := tx.factory.NewVariableStatement( + varStatement := tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList(variables), + tx.Factory().NewNodeList(variables), ), ) - tx.emitContext.SetOriginal(varStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) + tx.EmitContext().SetOriginal(varStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) statements = append(statements, varStatement) statements = tx.appendExportsOfImportDeclaration(statements, node) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } func (tx *CommonJSModuleTransformer) visitTopLevelImportEqualsDeclaration(node *ast.ImportEqualsDeclaration) *ast.Node { @@ -780,7 +781,7 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportEqualsDeclaration(node * var statements []*ast.Statement if ast.HasSyntacticModifier(node.AsNode(), ast.ModifierFlagsExport) { // export import m = require("mod"); - statement := tx.factory.NewExpressionStatement( + statement := tx.Factory().NewExpressionStatement( tx.createExportExpression( node.Name(), tx.createRequireCall(node.AsNode()), @@ -789,18 +790,18 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportEqualsDeclaration(node * ), ) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) statements = append(statements, statement) } else { // import m = require("mod"); - statement := tx.factory.NewVariableStatement( + statement := tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.VariableDeclarationNode{ - tx.factory.NewVariableDeclaration( - node.Name().Clone(tx.factory), + tx.Factory().NewNodeList([]*ast.VariableDeclarationNode{ + tx.Factory().NewVariableDeclaration( + node.Name().Clone(tx.Factory()), nil, /*exclamationToken*/ nil, /*typeNode*/ tx.createRequireCall(node.AsNode()), @@ -808,13 +809,13 @@ func (tx *CommonJSModuleTransformer) visitTopLevelImportEqualsDeclaration(node * }), ), ) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) statements = append(statements, statement) } statements = tx.appendExportsOfDeclaration(statements, node.AsNode(), nil /*seen*/, false /*liveBinding*/) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.ExportDeclaration) *ast.Node { @@ -824,16 +825,16 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.Ex return nil } - generatedName := tx.factory.NewGeneratedNameForNode(node.AsNode()) + generatedName := tx.Factory().NewGeneratedNameForNode(node.AsNode()) if node.ExportClause != nil && ast.IsNamedExports(node.ExportClause) { // export { x, y } from "mod"; var statements []*ast.Statement - varStatement := tx.factory.NewVariableStatement( + varStatement := tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.VariableDeclarationNode{ - tx.factory.NewVariableDeclaration( + tx.Factory().NewNodeList([]*ast.VariableDeclarationNode{ + tx.Factory().NewVariableDeclaration( generatedName, nil, /*exclamationToken*/ nil, /*type*/ @@ -842,37 +843,37 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.Ex }), ), ) - tx.emitContext.SetOriginal(varStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) + tx.EmitContext().SetOriginal(varStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) statements = append(statements, varStatement) for _, specifier := range node.ExportClause.AsNamedExports().Elements.Nodes { specifierName := specifier.PropertyNameOrName() exportNeedsImportDefault := tx.compilerOptions.GetESModuleInterop() && - tx.emitContext.EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper == 0 && + tx.EmitContext().EmitFlags(node.AsNode())&printer.EFNeverApplyImportHelper == 0 && ast.ModuleExportNameIsDefault(specifierName) var target *ast.Node if exportNeedsImportDefault { - target = tx.factory.NewImportDefaultHelper(generatedName) + target = tx.Factory().NewImportDefaultHelper(generatedName) } else { target = generatedName } var exportName *ast.Node if ast.IsStringLiteral(specifier.Name()) { - exportName = tx.factory.NewStringLiteralFromNode(specifier.Name()) + exportName = tx.Factory().NewStringLiteralFromNode(specifier.Name()) } else { - exportName = tx.factory.GetExportName(specifier.AsNode()) + exportName = tx.Factory().GetExportName(specifier.AsNode()) } var exportedValue *ast.Node if ast.IsStringLiteral(specifierName) { - exportedValue = tx.factory.NewElementAccessExpression(target, nil /*questionDotToken*/, specifierName, ast.NodeFlagsNone) + exportedValue = tx.Factory().NewElementAccessExpression(target, nil /*questionDotToken*/, specifierName, ast.NodeFlagsNone) } else { - exportedValue = tx.factory.NewPropertyAccessExpression(target, nil /*questionDotToken*/, specifierName, ast.NodeFlagsNone) + exportedValue = tx.Factory().NewPropertyAccessExpression(target, nil /*questionDotToken*/, specifierName, ast.NodeFlagsNone) } - statement := tx.factory.NewExpressionStatement( + statement := tx.Factory().NewExpressionStatement( tx.createExportExpression( exportName, exportedValue, @@ -880,12 +881,12 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.Ex true, /*liveBinding*/ ), ) - tx.emitContext.SetOriginal(statement, specifier.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, specifier.AsNode()) + tx.EmitContext().SetOriginal(statement, specifier.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, specifier.AsNode()) statements = append(statements, statement) } - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } if node.ExportClause != nil { @@ -893,11 +894,11 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.Ex // export * as default from "mod"; var exportName *ast.Node if ast.IsStringLiteral(node.ExportClause.Name()) { - exportName = tx.factory.NewStringLiteralFromNode(node.ExportClause.Name()) + exportName = tx.Factory().NewStringLiteralFromNode(node.ExportClause.Name()) } else { - exportName = node.ExportClause.Name().Clone(tx.factory) + exportName = node.ExportClause.Name().Clone(tx.Factory()) } - statement := tx.factory.NewExpressionStatement( + statement := tx.Factory().NewExpressionStatement( tx.createExportExpression( exportName, tx.getHelperExpressionForExport( @@ -908,17 +909,17 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportDeclaration(node *ast.Ex false, /*liveBinding*/ ), ) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) return statement } // export * from "mod"; - statement := tx.factory.NewExpressionStatement( - tx.visitor.VisitNode(tx.factory.NewExportStarHelper(tx.createRequireCall(node.AsNode()), tx.factory.NewIdentifier("exports"))), + statement := tx.Factory().NewExpressionStatement( + tx.Visitor().VisitNode(tx.Factory().NewExportStarHelper(tx.createRequireCall(node.AsNode()), tx.Factory().NewIdentifier("exports"))), ) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) return statement } @@ -928,8 +929,8 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportAssignment(node *ast.Exp } return tx.createExportStatement( - tx.factory.NewIdentifier("default"), - tx.visitor.VisitNode(node.Expression), + tx.Factory().NewIdentifier("default"), + tx.Visitor().VisitNode(node.Expression), &node.Loc, /*location*/ true, /*allowComments*/ false, /*liveBinding*/ @@ -938,37 +939,37 @@ func (tx *CommonJSModuleTransformer) visitTopLevelExportAssignment(node *ast.Exp func (tx *CommonJSModuleTransformer) visitTopLevelFunctionDeclaration(node *ast.FunctionDeclaration) *ast.Node { if ast.HasSyntacticModifier(node.AsNode(), ast.ModifierFlagsExport) { - return tx.factory.UpdateFunctionDeclaration( + return tx.Factory().UpdateFunctionDeclaration( node, - extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault), + transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault), node.AsteriskToken, - tx.factory.GetDeclarationName(node.AsNode()), + tx.Factory().GetDeclarationName(node.AsNode()), nil, /*typeParameters*/ - tx.visitor.VisitNodes(node.Parameters), + tx.Visitor().VisitNodes(node.Parameters), nil, /*type*/ - tx.visitor.VisitNode(node.Body), + tx.Visitor().VisitNode(node.Body), ) } else { - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } } func (tx *CommonJSModuleTransformer) visitTopLevelClassDeclaration(node *ast.ClassDeclaration) *ast.Node { var statements []*ast.Statement if ast.HasSyntacticModifier(node.AsNode(), ast.ModifierFlagsExport) { - statements = append(statements, tx.factory.UpdateClassDeclaration( + statements = append(statements, tx.Factory().UpdateClassDeclaration( node, - tx.visitor.VisitModifiers(extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault)), - tx.factory.GetDeclarationName(node.AsNode()), + tx.Visitor().VisitModifiers(transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault)), + tx.Factory().GetDeclarationName(node.AsNode()), nil, /*typeParameters*/ - tx.visitor.VisitNodes(node.HeritageClauses), - tx.visitor.VisitNodes(node.Members), + tx.Visitor().VisitNodes(node.HeritageClauses), + tx.Visitor().VisitNodes(node.Members), )) } else { - statements = append(statements, tx.visitor.VisitEachChild(node.AsNode())) + statements = append(statements, tx.Visitor().VisitEachChild(node.AsNode())) } statements = tx.appendExportsOfClassOrFunctionDeclaration(statements, node.AsNode()) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.VariableStatement) *ast.Node { @@ -981,18 +982,18 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va commitPendingVariables := func() { if len(variables) > 0 { - variableList := tx.factory.NewNodeList(variables) + variableList := tx.Factory().NewNodeList(variables) variableList.Loc = node.DeclarationList.AsVariableDeclarationList().Declarations.Loc - statement := tx.factory.UpdateVariableStatement( + statement := tx.Factory().UpdateVariableStatement( node, modifiers, - tx.factory.UpdateVariableDeclarationList( + tx.Factory().UpdateVariableDeclarationList( node.DeclarationList.AsVariableDeclarationList(), variableList, ), ) if len(statements) > 0 { - tx.emitContext.AddEmitFlags(statement, printer.EFNoComments) + tx.EmitContext().AddEmitFlags(statement, printer.EFNoComments) } statements = append(statements, statement) variables = nil @@ -1001,10 +1002,10 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va commitPendingExpressions := func() { if len(expressions) > 0 { - statement := tx.factory.NewExpressionStatement(tx.factory.InlineExpressions(expressions)) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + statement := tx.Factory().NewExpressionStatement(tx.Factory().InlineExpressions(expressions)) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) if len(statements) > 0 { - tx.emitContext.AddEmitFlags(statement, printer.EFNoComments) + tx.EmitContext().AddEmitFlags(statement, printer.EFNoComments) } statements = append(statements, statement) expressions = nil @@ -1025,7 +1026,7 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va for _, variable := range node.DeclarationList.AsVariableDeclarationList().Declarations.Nodes { v := variable.AsVariableDeclaration() - if ast.IsIdentifier(v.Name()) && isLocalName(tx.emitContext, v.Name()) { + if ast.IsIdentifier(v.Name()) && transformers.IsLocalName(tx.EmitContext(), v.Name()) { // A "local name" generally means a variable declaration that *shouldn't* be // converted to `exports.x = ...`, even if the declaration is exported. This // usually indicates a class or function declaration that was converted into @@ -1034,18 +1035,18 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va // an `export { x }` declaration will follow. if modifiers == nil { - modifiers = extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault) + modifiers = transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault) } if v.Initializer != nil { - variable = tx.factory.UpdateVariableDeclaration( + variable = tx.Factory().UpdateVariableDeclaration( v, v.Name(), nil, /*exclamationToken*/ nil, /*type*/ tx.createExportExpression( v.Name(), - tx.visitor.VisitNode(v.Initializer), + tx.Visitor().VisitNode(v.Initializer), nil, false, /*liveBinding*/ ), @@ -1056,29 +1057,29 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va } else if v.Initializer != nil && !ast.IsBindingPattern(v.Name()) && (ast.IsArrowFunction(v.Initializer) || (ast.IsFunctionExpression(v.Initializer) || ast.IsClassExpression(v.Initializer)) && v.Initializer.Name() == nil) { // preserve variable declarations for functions and classes to assign names - pushVariable(tx.factory.NewVariableDeclaration( + pushVariable(tx.Factory().NewVariableDeclaration( v.Name(), v.ExclamationToken, v.Type, - tx.visitor.VisitNode(v.Initializer), + tx.Visitor().VisitNode(v.Initializer), )) - propertyAccess := tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("exports"), + propertyAccess := tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ v.Name(), ast.NodeFlagsNone, ) - tx.emitContext.AssignCommentAndSourceMapRanges(propertyAccess, v.Name()) + tx.EmitContext().AssignCommentAndSourceMapRanges(propertyAccess, v.Name()) - pushExpression(tx.factory.NewAssignmentExpression( + pushExpression(tx.Factory().NewAssignmentExpression( propertyAccess, - v.Name().Clone(tx.factory), + v.Name().Clone(tx.Factory()), )) } else { - expression := convertVariableDeclarationToAssignmentExpression(tx.emitContext, v) + expression := transformers.ConvertVariableDeclarationToAssignmentExpression(tx.EmitContext(), v) if expression != nil { - pushExpression(tx.visitor.VisitNode(expression)) + pushExpression(tx.Visitor().VisitNode(expression)) } } } @@ -1086,7 +1087,7 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va commitPendingVariables() commitPendingExpressions() statements = tx.appendExportsOfVariableStatement(statements, node) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } return tx.visitTopLevelNestedVariableStatement(node) } @@ -1095,9 +1096,9 @@ func (tx *CommonJSModuleTransformer) visitTopLevelVariableStatement(node *ast.Va // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedVariableStatement(node *ast.VariableStatement) *ast.Node { var statements []*ast.Statement - statements = append(statements, tx.visitor.VisitEachChild(node.AsNode())) + statements = append(statements, tx.Visitor().VisitEachChild(node.AsNode())) statements = tx.appendExportsOfVariableStatement(statements, node) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } // Visits a top-level nested `for` statement as it may contain `var` declarations that are hoisted and may still be @@ -1116,29 +1117,29 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedForStatement(node *ast.F var statements []*ast.Statement varDeclList := tx.discardedValueVisitor.VisitNode(node.Initializer) - varStatement := tx.factory.NewVariableStatement(nil /*modifiers*/, varDeclList) + varStatement := tx.Factory().NewVariableStatement(nil /*modifiers*/, varDeclList) statements = append(statements, varStatement) statements = append(statements, exportStatements...) - condition := tx.visitor.VisitNode(node.Condition) + condition := tx.Visitor().VisitNode(node.Condition) incrementor := tx.discardedValueVisitor.VisitNode(node.Incrementor) - body := tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor) - statements = append(statements, tx.factory.UpdateForStatement( + body := tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor) + statements = append(statements, tx.Factory().UpdateForStatement( node, nil, /*initializer*/ condition, incrementor, body, )) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } } - return tx.factory.UpdateForStatement( + return tx.Factory().UpdateForStatement( node, tx.discardedValueVisitor.VisitNode(node.Initializer), - tx.visitor.VisitNode(node.Condition), + tx.Visitor().VisitNode(node.Condition), tx.discardedValueVisitor.VisitNode(node.Incrementor), - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), ) } @@ -1160,54 +1161,54 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedForInOrOfStatement(node // } initializer := tx.discardedValueVisitor.VisitNode(node.Initializer) - expression := tx.visitor.VisitNode(node.Expression) - body := tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor) + expression := tx.Visitor().VisitNode(node.Expression) + body := tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor) if ast.IsBlock(body) { block := body.AsBlock() bodyStatements := append(exportStatements, block.Statements.Nodes...) - bodyStatementList := tx.factory.NewNodeList(bodyStatements) + bodyStatementList := tx.Factory().NewNodeList(bodyStatements) bodyStatementList.Loc = block.Statements.Loc - body = tx.factory.UpdateBlock(block, bodyStatementList) + body = tx.Factory().UpdateBlock(block, bodyStatementList) } else { bodyStatements := append(exportStatements, body) - body = tx.factory.NewBlock(tx.factory.NewNodeList(bodyStatements), true /*multiLine*/) + body = tx.Factory().NewBlock(tx.Factory().NewNodeList(bodyStatements), true /*multiLine*/) } - return tx.factory.UpdateForInOrOfStatement(node, node.AwaitModifier, initializer, expression, body) + return tx.Factory().UpdateForInOrOfStatement(node, node.AwaitModifier, initializer, expression, body) } } - return tx.factory.UpdateForInOrOfStatement( + return tx.Factory().UpdateForInOrOfStatement( node, node.AwaitModifier, tx.discardedValueVisitor.VisitNode(node.Initializer), - tx.visitor.VisitNode(node.Expression), - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.Visitor().VisitNode(node.Expression), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), ) } // Visits a top-level nested `do` statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedDoStatement(node *ast.DoStatement) *ast.Node { - return tx.factory.UpdateDoStatement( + return tx.Factory().UpdateDoStatement( node, - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), - tx.visitor.VisitNode(node.Expression), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.Visitor().VisitNode(node.Expression), ) } // Visits a top-level nested `while` statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedWhileStatement(node *ast.WhileStatement) *ast.Node { - return tx.factory.UpdateWhileStatement( + return tx.Factory().UpdateWhileStatement( node, - tx.visitor.VisitNode(node.Expression), - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.Visitor().VisitNode(node.Expression), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), ) } // Visits a top-level nested labeled statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedLabeledStatement(node *ast.LabeledStatement) *ast.Node { - return tx.factory.UpdateLabeledStatement( + return tx.Factory().UpdateLabeledStatement( node, node.Label, tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.Statement), @@ -1217,9 +1218,9 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedLabeledStatement(node *a // Visits a top-level nested `with` statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedWithStatement(node *ast.WithStatement) *ast.Node { - return tx.factory.UpdateWithStatement( + return tx.Factory().UpdateWithStatement( node, - tx.visitor.VisitNode(node.Expression), + tx.Visitor().VisitNode(node.Expression), tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.Statement), ) } @@ -1227,9 +1228,9 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedWithStatement(node *ast. // Visits a top-level nested `if` statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedIfStatement(node *ast.IfStatement) *ast.Node { - return tx.factory.UpdateIfStatement( + return tx.Factory().UpdateIfStatement( node, - tx.visitor.VisitNode(node.Expression), + tx.Visitor().VisitNode(node.Expression), tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ThenStatement), tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ElseStatement), ) @@ -1238,9 +1239,9 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedIfStatement(node *ast.If // Visits a top-level nested `switch` statement as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedSwitchStatement(node *ast.SwitchStatement) *ast.Node { - return tx.factory.UpdateSwitchStatement( + return tx.Factory().UpdateSwitchStatement( node, - tx.visitor.VisitNode(node.Expression), + tx.Visitor().VisitNode(node.Expression), tx.topLevelNestedVisitor.VisitNode(node.CaseBlock), ) } @@ -1254,9 +1255,9 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedCaseBlock(node *ast.Case // Visits a top-level nested `case` or `default` clause as it may contain `var` declarations that are hoisted and may // still be exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedCaseOrDefaultClause(node *ast.CaseOrDefaultClause) *ast.Node { - return tx.factory.UpdateCaseOrDefaultClause( + return tx.Factory().UpdateCaseOrDefaultClause( node, - tx.visitor.VisitNode(node.Expression), + tx.Visitor().VisitNode(node.Expression), tx.topLevelNestedVisitor.VisitNodes(node.Statements), ) } @@ -1270,7 +1271,7 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedTryStatement(node *ast.T // Visits a top-level nested `catch` clause as it may contain `var` declarations that are hoisted and may still be // exported with `export {}`. func (tx *CommonJSModuleTransformer) visitTopLevelNestedCatchClause(node *ast.CatchClause) *ast.Node { - return tx.factory.UpdateCatchClause( + return tx.Factory().UpdateCatchClause( node, node.VariableDeclaration, tx.topLevelNestedVisitor.VisitNode(node.Block), @@ -1284,22 +1285,22 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedBlock(node *ast.Block) * } func (tx *CommonJSModuleTransformer) visitForStatement(node *ast.ForStatement) *ast.Node { - return tx.factory.UpdateForStatement( + return tx.Factory().UpdateForStatement( node, tx.discardedValueVisitor.VisitNode(node.Initializer), - tx.visitor.VisitNode(node.Condition), + tx.Visitor().VisitNode(node.Condition), tx.discardedValueVisitor.VisitNode(node.Incrementor), - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), ) } func (tx *CommonJSModuleTransformer) visitForInOrOfStatement(node *ast.ForInOrOfStatement) *ast.Node { - return tx.factory.UpdateForInOrOfStatement( + return tx.Factory().UpdateForInOrOfStatement( node, node.AwaitModifier, tx.discardedValueVisitor.VisitNode(node.Initializer), - tx.visitor.VisitNode(node.Expression), - tx.emitContext.VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), + tx.Visitor().VisitNode(node.Expression), + tx.EmitContext().VisitIterationBody(node.Statement, tx.topLevelNestedVisitor), ) } @@ -1315,14 +1316,14 @@ func (tx *CommonJSModuleTransformer) visitVoidExpression(node *ast.VoidExpressio // Visits a parenthesized expression whose value may be discarded at runtime. func (tx *CommonJSModuleTransformer) visitParenthesizedExpression(node *ast.ParenthesizedExpression, resultIsDiscarded bool) *ast.Node { - expression := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.visitor).VisitNode(node.Expression) - return tx.factory.UpdateParenthesizedExpression(node, expression) + expression := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.Visitor()).VisitNode(node.Expression) + return tx.Factory().UpdateParenthesizedExpression(node, expression) } // Visits a partially emitted expression whose value may be discarded at runtime. func (tx *CommonJSModuleTransformer) visitPartiallyEmittedExpression(node *ast.PartiallyEmittedExpression, resultIsDiscarded bool) *ast.Node { - expression := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.visitor).VisitNode(node.Expression) - return tx.factory.UpdatePartiallyEmittedExpression(node, expression) + expression := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.Visitor()).VisitNode(node.Expression) + return tx.Factory().UpdatePartiallyEmittedExpression(node, expression) } // Visits a binary expression whose value may be discarded, or which might contain an assignment to an exported @@ -1336,7 +1337,7 @@ func (tx *CommonJSModuleTransformer) visitBinaryExpression(node *ast.BinaryExpre return tx.visitCommaExpression(node, resultIsDiscarded) } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } func (tx *CommonJSModuleTransformer) visitAssignmentExpression(node *ast.BinaryExpression) *ast.Node { @@ -1351,12 +1352,12 @@ func (tx *CommonJSModuleTransformer) visitAssignmentExpression(node *ast.BinaryE // - We do not transform identifiers tagged with the LocalName flag. // - We only transform identifiers that are exported at the top level. if ast.IsIdentifier(node.Left) && - (!isGeneratedIdentifier(tx.emitContext, node.Left) || isFileLevelReservedGeneratedIdentifier(tx.emitContext, node.Left)) && - !isLocalName(tx.emitContext, node.Left) { + (!transformers.IsGeneratedIdentifier(tx.EmitContext(), node.Left) || isFileLevelReservedGeneratedIdentifier(tx.EmitContext(), node.Left)) && + !transformers.IsLocalName(tx.EmitContext(), node.Left) { exportedNames := tx.getExports(node.Left) if len(exportedNames) > 0 { // For each additional export of the declaration, apply an export assignment. - expression := tx.visitor.VisitEachChild(node.AsNode()) + expression := tx.Visitor().VisitEachChild(node.AsNode()) for _, exportName := range exportedNames { expression = tx.createExportExpression(exportName, expression, &node.Loc /*location*/, false /*liveBinding*/) } @@ -1364,26 +1365,26 @@ func (tx *CommonJSModuleTransformer) visitAssignmentExpression(node *ast.BinaryE } } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } // Visits a destructuring assignment which might target an exported identifier. func (tx *CommonJSModuleTransformer) visitDestructuringAssignment(node *ast.BinaryExpression) *ast.Node { - return tx.factory.UpdateBinaryExpression( + return tx.Factory().UpdateBinaryExpression( node, nil, /*modifiers*/ tx.assignmentPatternVisitor.VisitNode(node.Left), nil, /*typeNode*/ node.OperatorToken, - tx.visitor.VisitNode(node.Right), + tx.Visitor().VisitNode(node.Right), ) } func (tx *CommonJSModuleTransformer) visitAssignmentProperty(node *ast.PropertyAssignment) *ast.Node { - return tx.factory.UpdatePropertyAssignment( + return tx.Factory().UpdatePropertyAssignment( node, nil, /*modifiers*/ - tx.visitor.VisitNode(node.Name()), + tx.Visitor().VisitNode(node.Name()), nil, /*postfixToken*/ nil, /*typeNode*/ tx.assignmentPatternVisitor.VisitNode(node.Initializer), @@ -1393,50 +1394,50 @@ func (tx *CommonJSModuleTransformer) visitAssignmentProperty(node *ast.PropertyA func (tx *CommonJSModuleTransformer) visitShorthandAssignmentProperty(node *ast.ShorthandPropertyAssignment) *ast.Node { target := tx.visitDestructuringAssignmentTargetNoStack(node.Name()) if ast.IsIdentifier(target) { - return tx.factory.UpdateShorthandPropertyAssignment( + return tx.Factory().UpdateShorthandPropertyAssignment( node, nil, /*modifiers*/ target, nil, /*postfixToken*/ nil, /*typeNode*/ node.EqualsToken, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } if node.ObjectAssignmentInitializer != nil { equalsToken := node.EqualsToken if equalsToken == nil { - equalsToken = tx.factory.NewToken(ast.KindEqualsToken) + equalsToken = tx.Factory().NewToken(ast.KindEqualsToken) } - target = tx.factory.NewBinaryExpression( + target = tx.Factory().NewBinaryExpression( nil, /*modifiers*/ target, nil, /*typeNode*/ equalsToken, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } - updated := tx.factory.NewPropertyAssignment( + updated := tx.Factory().NewPropertyAssignment( nil, /*modifiers*/ node.Name(), nil, /*postfixToken*/ nil, /*typeNode*/ target, ) - tx.emitContext.SetOriginal(updated, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(updated, node.AsNode()) + tx.EmitContext().SetOriginal(updated, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(updated, node.AsNode()) return updated } func (tx *CommonJSModuleTransformer) visitAssignmentRestProperty(node *ast.SpreadAssignment) *ast.Node { - return tx.factory.UpdateSpreadAssignment( + return tx.Factory().UpdateSpreadAssignment( node, tx.visitDestructuringAssignmentTarget(node.Expression), ) } func (tx *CommonJSModuleTransformer) visitAssignmentRestElement(node *ast.SpreadElement) *ast.Node { - return tx.factory.UpdateSpreadElement( + return tx.Factory().UpdateSpreadElement( node, tx.visitDestructuringAssignmentTarget(node.Expression), ) @@ -1446,13 +1447,13 @@ func (tx *CommonJSModuleTransformer) visitAssignmentElement(node *ast.Node) *ast if ast.IsBinaryExpression(node) { n := node.AsBinaryExpression() if n.OperatorToken.Kind == ast.KindEqualsToken { - return tx.factory.UpdateBinaryExpression( + return tx.Factory().UpdateBinaryExpression( n, nil, /*modifiers*/ tx.visitDestructuringAssignmentTarget(n.Left), nil, /*typeNode*/ n.OperatorToken, - tx.visitor.VisitNode(n.Right), + tx.Visitor().VisitNode(n.Right), ) } } @@ -1475,8 +1476,8 @@ func (tx *CommonJSModuleTransformer) visitDestructuringAssignmentTarget(node *as func (tx *CommonJSModuleTransformer) visitDestructuringAssignmentTargetNoStack(node *ast.Node) *ast.Node { if ast.IsIdentifier(node) && - (!isGeneratedIdentifier(tx.emitContext, node) || isFileLevelReservedGeneratedIdentifier(tx.emitContext, node)) && - !isLocalName(tx.emitContext, node) { + (!transformers.IsGeneratedIdentifier(tx.EmitContext(), node) || isFileLevelReservedGeneratedIdentifier(tx.EmitContext(), node)) && + !transformers.IsLocalName(tx.EmitContext(), node) { expression := tx.visitExpressionIdentifier(node) exportedNames := tx.getExports(node) if len(exportedNames) > 0 { @@ -1487,18 +1488,18 @@ func (tx *CommonJSModuleTransformer) visitDestructuringAssignmentTargetNoStack(n // to: // { x: { set value(v) { exports.x = x = v; } }.value } = y - value := tx.factory.NewUniqueNameEx("value", printer.AutoGenerateOptions{ + value := tx.Factory().NewUniqueNameEx("value", printer.AutoGenerateOptions{ Flags: printer.GeneratedIdentifierFlagsOptimistic, }) - expression = tx.factory.NewAssignmentExpression(expression, value) + expression = tx.Factory().NewAssignmentExpression(expression, value) for _, exportName := range exportedNames { expression = tx.createExportExpression(exportName, expression, nil /*location*/, false /*liveBinding*/) } - statement := tx.factory.NewExpressionStatement(expression) - statementList := tx.factory.NewNodeList([]*ast.Node{statement}) - param := tx.factory.NewParameterDeclaration( + statement := tx.Factory().NewExpressionStatement(expression) + statementList := tx.Factory().NewNodeList([]*ast.Node{statement}) + param := tx.Factory().NewParameterDeclaration( nil, /*modifiers*/ nil, /*dotDotDotToken*/ value, @@ -1506,17 +1507,17 @@ func (tx *CommonJSModuleTransformer) visitDestructuringAssignmentTargetNoStack(n nil, /*type*/ nil, /*initializer*/ ) - valueSetter := tx.factory.NewSetAccessorDeclaration( + valueSetter := tx.Factory().NewSetAccessorDeclaration( nil, /*modifiers*/ - tx.factory.NewIdentifier("value"), + tx.Factory().NewIdentifier("value"), nil, /*typeParameters*/ - tx.factory.NewNodeList([]*ast.Node{param}), + tx.Factory().NewNodeList([]*ast.Node{param}), nil, /*returnType*/ - tx.factory.NewBlock(statementList, false /*multiLine*/), + tx.Factory().NewBlock(statementList, false /*multiLine*/), ) - propertyList := tx.factory.NewNodeList([]*ast.Node{valueSetter}) - expression = tx.factory.NewObjectLiteralExpression(propertyList, false /*multiLine*/) - expression = tx.factory.NewPropertyAccessExpression(expression, nil /*questionDotToken*/, tx.factory.NewIdentifier("value"), ast.NodeFlagsNone) + propertyList := tx.Factory().NewNodeList([]*ast.Node{valueSetter}) + expression = tx.Factory().NewObjectLiteralExpression(propertyList, false /*multiLine*/) + expression = tx.Factory().NewPropertyAccessExpression(expression, nil /*questionDotToken*/, tx.Factory().NewIdentifier("value"), ast.NodeFlagsNone) } return expression } @@ -1527,8 +1528,8 @@ func (tx *CommonJSModuleTransformer) visitDestructuringAssignmentTargetNoStack(n // Visits a comma expression whose left-hand value is always discard, and whose right-hand value may be discarded at runtime. func (tx *CommonJSModuleTransformer) visitCommaExpression(node *ast.BinaryExpression, resultIsDiscarded bool) *ast.Node { left := tx.discardedValueVisitor.VisitNode(node.Left) - right := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.visitor).VisitNode(node.Right) - return tx.factory.UpdateBinaryExpression(node, nil /*modifiers*/, left, nil /*typeNode*/, node.OperatorToken, right) + right := core.IfElse(resultIsDiscarded, tx.discardedValueVisitor, tx.Visitor()).VisitNode(node.Right) + return tx.Factory().UpdateBinaryExpression(node, nil /*modifiers*/, left, nil /*typeNode*/, node.OperatorToken, right) } // Visits a prefix unary expression that might modify an exported identifier. @@ -1544,7 +1545,7 @@ func (tx *CommonJSModuleTransformer) visitPrefixUnaryExpression(node *ast.Prefix // - We only transform identifiers that are exported at the top level. if (node.Operator == ast.KindPlusPlusToken || node.Operator == ast.KindMinusMinusToken) && ast.IsIdentifier(node.Operand) && - !isLocalName(tx.emitContext, node.Operand) { + !transformers.IsLocalName(tx.EmitContext(), node.Operand) { exportedNames := tx.getExports(node.Operand) if len(exportedNames) > 0 { // given: @@ -1558,15 +1559,15 @@ func (tx *CommonJSModuleTransformer) visitPrefixUnaryExpression(node *ast.Prefix // note: // after the operation, `exports.x` will hold the value of `x` after the increment. - expression := tx.factory.UpdatePrefixUnaryExpression(node, tx.visitor.VisitNode(node.Operand)) + expression := tx.Factory().UpdatePrefixUnaryExpression(node, tx.Visitor().VisitNode(node.Operand)) for _, exportName := range exportedNames { expression = tx.createExportExpression(exportName, expression, nil /*location*/, false /*liveBinding*/) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) } return expression } } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } // Visits a postfix unary expression that might modify an exported identifier. @@ -1582,7 +1583,7 @@ func (tx *CommonJSModuleTransformer) visitPostfixUnaryExpression(node *ast.Postf // - We only transform identifiers that are exported at the top level. if (node.Operator == ast.KindPlusPlusToken || node.Operator == ast.KindMinusMinusToken) && ast.IsIdentifier(node.Operand) && - !isLocalName(tx.emitContext, node.Operand) { + !transformers.IsLocalName(tx.EmitContext(), node.Operand) { exportedNames := tx.getExports(node.Operand) if len(exportedNames) > 0 { // given (value is discarded): @@ -1610,33 +1611,33 @@ func (tx *CommonJSModuleTransformer) visitPostfixUnaryExpression(node *ast.Postf // `y` will hold the value of `x` before the increment. var temp *ast.IdentifierNode - expression := tx.factory.UpdatePostfixUnaryExpression(node, tx.visitor.VisitNode(node.Operand)) + expression := tx.Factory().UpdatePostfixUnaryExpression(node, tx.Visitor().VisitNode(node.Operand)) if !resultIsDiscarded { - temp = tx.factory.NewTempVariable() - tx.emitContext.AddVariableDeclaration(temp) + temp = tx.Factory().NewTempVariable() + tx.EmitContext().AddVariableDeclaration(temp) - expression = tx.factory.NewAssignmentExpression(temp, expression) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + expression = tx.Factory().NewAssignmentExpression(temp, expression) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) } - expression = tx.factory.NewCommaExpression(expression, node.Operand.Clone(tx.factory)) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + expression = tx.Factory().NewCommaExpression(expression, node.Operand.Clone(tx.Factory())) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) for _, exportName := range exportedNames { expression = tx.createExportExpression(exportName, expression, nil /*location*/, false /*liveBinding*/) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) } if temp != nil { - expression = tx.factory.NewCommaExpression(expression, temp.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + expression = tx.Factory().NewCommaExpression(expression, temp.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) } return expression } } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } // Visits a call expression that might reference an imported symbol and thus require an indirect call, or that might @@ -1656,8 +1657,8 @@ func (tx *CommonJSModuleTransformer) visitCallExpression(node *ast.CallExpressio return tx.shimOrRewriteImportOrRequireCall(node.AsCallExpression()) } if ast.IsIdentifier(node.Expression) && - !isGeneratedIdentifier(tx.emitContext, node.Expression) && - !isHelperName(tx.emitContext, node.Expression) { + !transformers.IsGeneratedIdentifier(tx.EmitContext(), node.Expression) && + !transformers.IsHelperName(tx.EmitContext(), node.Expression) { // given: // import { f } from "mod"; // f(); @@ -1667,19 +1668,19 @@ func (tx *CommonJSModuleTransformer) visitCallExpression(node *ast.CallExpressio // note: // the indirect call is applied by the printer by way of the `EFIndirectCall` emit flag. expression := tx.visitExpressionIdentifier(node.Expression) - updated := tx.factory.UpdateCallExpression( + updated := tx.Factory().UpdateCallExpression( node, expression, node.QuestionDotToken, nil, /*typeArguments*/ - tx.visitor.VisitNodes(node.Arguments), + tx.Visitor().VisitNodes(node.Arguments), ) if !ast.IsIdentifier(expression) { - tx.emitContext.AddEmitFlags(updated, printer.EFIndirectCall) + tx.EmitContext().AddEmitFlags(updated, printer.EFIndirectCall) } return updated } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } func (tx *CommonJSModuleTransformer) shouldTransformImportCall() bool { @@ -1688,11 +1689,11 @@ func (tx *CommonJSModuleTransformer) shouldTransformImportCall() bool { func (tx *CommonJSModuleTransformer) visitImportCallExpression(node *ast.CallExpression, rewriteOrShim bool) *ast.Node { if tx.moduleKind == core.ModuleKindNone && tx.languageVersion >= core.ScriptTargetES2020 { - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } - externalModuleName := getExternalModuleNameLiteral(tx.factory, node.AsNode(), tx.currentSourceFile, nil /*host*/, nil /*resolver*/, tx.compilerOptions) - firstArgument := tx.visitor.VisitNode(core.FirstOrNil(node.Arguments.Nodes)) + externalModuleName := getExternalModuleNameLiteral(tx.Factory(), node.AsNode(), tx.currentSourceFile, nil /*host*/, nil /*resolver*/, tx.compilerOptions) + firstArgument := tx.Visitor().VisitNode(core.FirstOrNil(node.Arguments.Nodes)) // Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output. var argument *ast.Expression @@ -1700,9 +1701,9 @@ func (tx *CommonJSModuleTransformer) visitImportCallExpression(node *ast.CallExp argument = externalModuleName } else if firstArgument != nil && rewriteOrShim { if ast.IsStringLiteral(firstArgument) { - argument = rewriteModuleSpecifier(tx.emitContext, firstArgument, tx.compilerOptions) + argument = rewriteModuleSpecifier(tx.EmitContext(), firstArgument, tx.compilerOptions) } else { - argument = tx.factory.NewRewriteRelativeImportExtensionsHelper(firstArgument, tx.compilerOptions.Jsx == core.JsxEmitPreserve) + argument = tx.Factory().NewRewriteRelativeImportExtensionsHelper(firstArgument, tx.compilerOptions.Jsx == core.JsxEmitPreserve) } } else { argument = firstArgument @@ -1724,55 +1725,55 @@ func (tx *CommonJSModuleTransformer) createImportCallExpressionCommonJS(arg *ast var promiseResolveArguments []*ast.Expression if needSyncEval { promiseResolveArguments = []*ast.Expression{ - tx.factory.NewTemplateExpression( - tx.factory.NewTemplateHead("", "", ast.TokenFlagsNone), - tx.factory.NewNodeList([]*ast.TemplateSpanNode{ - tx.factory.NewTemplateSpan(arg, tx.factory.NewTemplateTail("", "", ast.TokenFlagsNone)), + tx.Factory().NewTemplateExpression( + tx.Factory().NewTemplateHead("", "", ast.TokenFlagsNone), + tx.Factory().NewNodeList([]*ast.TemplateSpanNode{ + tx.Factory().NewTemplateSpan(arg, tx.Factory().NewTemplateTail("", "", ast.TokenFlagsNone)), }), ), } } - promiseResolveCall := tx.factory.NewCallExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("Promise"), + promiseResolveCall := tx.Factory().NewCallExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("Promise"), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("resolve"), + tx.Factory().NewIdentifier("resolve"), ast.NodeFlagsNone, ), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList(promiseResolveArguments), + tx.Factory().NewNodeList(promiseResolveArguments), ast.NodeFlagsNone, ) var requireArguments []*ast.Expression if needSyncEval { requireArguments = []*ast.Expression{ - tx.factory.NewIdentifier("s"), + tx.Factory().NewIdentifier("s"), } } else if arg != nil { requireArguments = []*ast.Expression{arg} } - requireCall := tx.factory.NewCallExpression( - tx.factory.NewIdentifier("require"), + requireCall := tx.Factory().NewCallExpression( + tx.Factory().NewIdentifier("require"), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList(requireArguments), + tx.Factory().NewNodeList(requireArguments), ast.NodeFlagsNone, ) if tx.compilerOptions.GetESModuleInterop() { - requireCall = tx.factory.NewImportStarHelper(requireCall) + requireCall = tx.Factory().NewImportStarHelper(requireCall) } var parameters []*ast.ParameterDeclarationNode if needSyncEval { parameters = []*ast.ParameterDeclarationNode{ - tx.factory.NewParameterDeclaration( + tx.Factory().NewParameterDeclaration( nil, /*modifiers*/ nil, /*dotDotDotToken*/ - tx.factory.NewIdentifier("s"), + tx.Factory().NewIdentifier("s"), nil, /*questionToken*/ nil, /*type*/ nil, /*initializer*/ @@ -1780,54 +1781,54 @@ func (tx *CommonJSModuleTransformer) createImportCallExpressionCommonJS(arg *ast } } - function := tx.factory.NewArrowFunction( + function := tx.Factory().NewArrowFunction( nil, /*modifiers*/ nil, /*typeParameters*/ - tx.factory.NewNodeList(parameters), + tx.Factory().NewNodeList(parameters), nil, /*type*/ - tx.factory.NewToken(ast.KindEqualsGreaterThanToken), /*equalsGreaterThanToken*/ + tx.Factory().NewToken(ast.KindEqualsGreaterThanToken), /*equalsGreaterThanToken*/ requireCall, ) - downleveledImport := tx.factory.NewCallExpression( - tx.factory.NewPropertyAccessExpression( + downleveledImport := tx.Factory().NewCallExpression( + tx.Factory().NewPropertyAccessExpression( promiseResolveCall, nil, /*questionDotToken*/ - tx.factory.NewIdentifier("then"), + tx.Factory().NewIdentifier("then"), ast.NodeFlagsNone, ), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList([]*ast.Expression{function}), + tx.Factory().NewNodeList([]*ast.Expression{function}), ast.NodeFlagsNone, ) return downleveledImport } func (tx *CommonJSModuleTransformer) shimOrRewriteImportOrRequireCall(node *ast.CallExpression) *ast.Node { - expression := tx.visitor.VisitNode(node.Expression) + expression := tx.Visitor().VisitNode(node.Expression) argumentsList := node.Arguments if len(node.Arguments.Nodes) > 0 { firstArgument := node.Arguments.Nodes[0] firstArgumentChanged := false if ast.IsStringLiteralLike(firstArgument) { - rewritten := rewriteModuleSpecifier(tx.emitContext, firstArgument, tx.compilerOptions) + rewritten := rewriteModuleSpecifier(tx.EmitContext(), firstArgument, tx.compilerOptions) firstArgumentChanged = rewritten != firstArgument firstArgument = rewritten } else { - firstArgument = tx.factory.NewRewriteRelativeImportExtensionsHelper(firstArgument, tx.compilerOptions.Jsx == core.JsxEmitPreserve) + firstArgument = tx.Factory().NewRewriteRelativeImportExtensionsHelper(firstArgument, tx.compilerOptions.Jsx == core.JsxEmitPreserve) firstArgumentChanged = true } - rest, restChanged := tx.visitor.VisitSlice(node.Arguments.Nodes[1:]) + rest, restChanged := tx.Visitor().VisitSlice(node.Arguments.Nodes[1:]) if firstArgumentChanged || restChanged { arguments := append([]*ast.Expression{firstArgument}, rest...) - argumentsList = tx.factory.NewNodeList(arguments) + argumentsList = tx.Factory().NewNodeList(arguments) argumentsList.Loc = node.Arguments.Loc } } - return tx.factory.UpdateCallExpression( + return tx.Factory().UpdateCallExpression( node, expression, node.QuestionDotToken, @@ -1838,7 +1839,7 @@ func (tx *CommonJSModuleTransformer) shimOrRewriteImportOrRequireCall(node *ast. // Visits a tagged template expression that might reference an imported symbol and thus require an indirect call. func (tx *CommonJSModuleTransformer) visitTaggedTemplateExpression(node *ast.TaggedTemplateExpression) *ast.Node { - if ast.IsIdentifier(node.Tag) && !isGeneratedIdentifier(tx.emitContext, node.Tag) && !isHelperName(tx.emitContext, node.Tag) { + if ast.IsIdentifier(node.Tag) && !transformers.IsGeneratedIdentifier(tx.EmitContext(), node.Tag) && !transformers.IsHelperName(tx.EmitContext(), node.Tag) { // given: // import { f } from "mod"; // f``; @@ -1849,19 +1850,19 @@ func (tx *CommonJSModuleTransformer) visitTaggedTemplateExpression(node *ast.Tag // the indirect call is applied by the printer by way of the `EFIndirectCall` emit flag. expression := tx.visitExpressionIdentifier(node.Tag) - updated := tx.factory.UpdateTaggedTemplateExpression( + updated := tx.Factory().UpdateTaggedTemplateExpression( node, expression, nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.visitor.VisitNode(node.Template), + tx.Visitor().VisitNode(node.Template), ) if !ast.IsIdentifier(expression) { - tx.emitContext.AddEmitFlags(updated, printer.EFIndirectCall) + tx.EmitContext().AddEmitFlags(updated, printer.EFIndirectCall) } return updated } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } // Visits a shorthand property assignment that might reference an imported or exported symbol. @@ -1873,29 +1874,29 @@ func (tx *CommonJSModuleTransformer) visitShorthandPropertyAssignment(node *ast. // destructuring assignment expression := exportedOrImportedName if node.ObjectAssignmentInitializer != nil { - expression = tx.factory.NewAssignmentExpression( + expression = tx.Factory().NewAssignmentExpression( expression, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } - assignment := tx.factory.NewPropertyAssignment(nil /*modifiers*/, name, nil /*postfixToken*/, nil /*typeNode*/, expression) + assignment := tx.Factory().NewPropertyAssignment(nil /*modifiers*/, name, nil /*postfixToken*/, nil /*typeNode*/, expression) assignment.Loc = node.Loc - tx.emitContext.AssignCommentAndSourceMapRanges(assignment, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(assignment, node.AsNode()) return assignment } - return tx.factory.UpdateShorthandPropertyAssignment(node, + return tx.Factory().UpdateShorthandPropertyAssignment(node, nil, /*modifiers*/ exportedOrImportedName, nil, /*postfixToken*/ nil, /*typeNode*/ node.EqualsToken, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } // Visits an identifier that, if it is in an expression position, might reference an imported or exported symbol. func (tx *CommonJSModuleTransformer) visitIdentifier(node *ast.IdentifierNode) *ast.Node { - if isIdentifierReference(node, tx.parentNode) { + if transformers.IsIdentifierReference(node, tx.parentNode) { return tx.visitExpressionIdentifier(node) } return node @@ -1903,59 +1904,59 @@ func (tx *CommonJSModuleTransformer) visitIdentifier(node *ast.IdentifierNode) * // Visits an identifier in an expression position that might reference an imported or exported symbol. func (tx *CommonJSModuleTransformer) visitExpressionIdentifier(node *ast.IdentifierNode) *ast.Node { - if info := tx.emitContext.GetAutoGenerateInfo(node); !(info != nil && !info.Flags.HasAllowNameSubstitution()) && - !isHelperName(tx.emitContext, node) && - !isLocalName(tx.emitContext, node) && - !isDeclarationNameOfEnumOrNamespace(tx.emitContext, node) { - exportContainer := tx.resolver.GetReferencedExportContainer(tx.emitContext.MostOriginal(node), isExportName(tx.emitContext, node)) + if info := tx.EmitContext().GetAutoGenerateInfo(node); !(info != nil && !info.Flags.HasAllowNameSubstitution()) && + !transformers.IsHelperName(tx.EmitContext(), node) && + !transformers.IsLocalName(tx.EmitContext(), node) && + !isDeclarationNameOfEnumOrNamespace(tx.EmitContext(), node) { + exportContainer := tx.resolver.GetReferencedExportContainer(tx.EmitContext().MostOriginal(node), transformers.IsExportName(tx.EmitContext(), node)) if exportContainer != nil && ast.IsSourceFile(exportContainer) { - reference := tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("exports"), + reference := tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("exports"), nil, /*questionDotToken*/ - node.Clone(tx.factory), + node.Clone(tx.Factory()), ast.NodeFlagsNone, ) - tx.emitContext.AssignCommentAndSourceMapRanges(reference, node) + tx.EmitContext().AssignCommentAndSourceMapRanges(reference, node) reference.Loc = node.Loc return reference } - importDeclaration := tx.resolver.GetReferencedImportDeclaration(tx.emitContext.MostOriginal(node)) + importDeclaration := tx.resolver.GetReferencedImportDeclaration(tx.EmitContext().MostOriginal(node)) if importDeclaration != nil { if ast.IsImportClause(importDeclaration) { - reference := tx.factory.NewPropertyAccessExpression( - tx.factory.NewGeneratedNameForNode(importDeclaration.Parent), + reference := tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewGeneratedNameForNode(importDeclaration.Parent), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("default"), + tx.Factory().NewIdentifier("default"), ast.NodeFlagsNone, ) - tx.emitContext.AssignCommentAndSourceMapRanges(reference, node) + tx.EmitContext().AssignCommentAndSourceMapRanges(reference, node) reference.Loc = node.Loc return reference } if ast.IsImportSpecifier(importDeclaration) { name := importDeclaration.AsImportSpecifier().PropertyNameOrName() decl := ast.FindAncestor(importDeclaration, ast.IsImportDeclaration) - target := tx.factory.NewGeneratedNameForNode(core.Coalesce(decl, importDeclaration)) + target := tx.Factory().NewGeneratedNameForNode(core.Coalesce(decl, importDeclaration)) var reference *ast.Node if ast.IsStringLiteral(name) { - reference = tx.factory.NewElementAccessExpression( + reference = tx.Factory().NewElementAccessExpression( target, nil, /*questionDotToken*/ - tx.factory.NewStringLiteralFromNode(name), + tx.Factory().NewStringLiteralFromNode(name), ast.NodeFlagsNone, ) } else { - referenceName := name.Clone(tx.factory) - tx.emitContext.AddEmitFlags(referenceName, printer.EFNoSourceMap|printer.EFNoComments) - reference = tx.factory.NewPropertyAccessExpression( + referenceName := name.Clone(tx.Factory()) + tx.EmitContext().AddEmitFlags(referenceName, printer.EFNoSourceMap|printer.EFNoComments) + reference = tx.Factory().NewPropertyAccessExpression( target, nil, /*questionDotToken*/ referenceName, ast.NodeFlagsNone, ) } - tx.emitContext.AssignCommentAndSourceMapRanges(reference, node) + tx.EmitContext().AssignCommentAndSourceMapRanges(reference, node) reference.Loc = node.Loc return reference } @@ -1966,8 +1967,8 @@ func (tx *CommonJSModuleTransformer) visitExpressionIdentifier(node *ast.Identif // Gets the exported names of an identifier, if it is exported. func (tx *CommonJSModuleTransformer) getExports(name *ast.IdentifierNode) []*ast.ModuleExportName { - if !isGeneratedIdentifier(tx.emitContext, name) { - importDeclaration := tx.resolver.GetReferencedImportDeclaration(tx.emitContext.MostOriginal(name)) + if !transformers.IsGeneratedIdentifier(tx.EmitContext(), name) { + importDeclaration := tx.resolver.GetReferencedImportDeclaration(tx.EmitContext().MostOriginal(name)) if importDeclaration != nil { return tx.currentModuleInfo.exportedBindings.Get(importDeclaration) } @@ -1976,7 +1977,7 @@ func (tx *CommonJSModuleTransformer) getExports(name *ast.IdentifierNode) []*ast // we analyze all value exports of a symbol. var bindingsSet collections.Set[*ast.ModuleExportName] var bindings []*ast.ModuleExportName - declarations := tx.resolver.GetReferencedValueDeclarations(tx.emitContext.MostOriginal(name)) + declarations := tx.resolver.GetReferencedValueDeclarations(tx.EmitContext().MostOriginal(name)) if declarations != nil { for _, declaration := range declarations { exportedBindings := tx.currentModuleInfo.exportedBindings.Get(declaration) @@ -1989,7 +1990,7 @@ func (tx *CommonJSModuleTransformer) getExports(name *ast.IdentifierNode) []*ast } return bindings } - } else if isFileLevelReservedGeneratedIdentifier(tx.emitContext, name) { + } else if isFileLevelReservedGeneratedIdentifier(tx.EmitContext(), name) { exportSpecifiers := tx.currentModuleInfo.exportSpecifiers.Get(name.Text()) if exportSpecifiers != nil { var exportedNames []*ast.ModuleExportName diff --git a/internal/transformers/commonjsmodule_test.go b/internal/transformers/moduletransforms/commonjsmodule_test.go similarity index 98% rename from internal/transformers/commonjsmodule_test.go rename to internal/transformers/moduletransforms/commonjsmodule_test.go index a62a3c4ff6..2e13a1fa95 100644 --- a/internal/transformers/commonjsmodule_test.go +++ b/internal/transformers/moduletransforms/commonjsmodule_test.go @@ -1,4 +1,4 @@ -package transformers +package moduletransforms_test import ( "testing" @@ -9,6 +9,8 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" + "github.com/microsoft/typescript-go/internal/transformers/moduletransforms" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" ) func fakeGetEmitModuleFormatOfFile(file ast.HasFileName) core.ModuleKind { @@ -1046,8 +1048,8 @@ exports.a = a;`, emitContext := printer.NewEmitContext() resolver := binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{}) - file = NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file) - file = NewCommonJSModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file) + file = tstransforms.NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file) + file = moduletransforms.NewCommonJSModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file) emittestutil.CheckEmit(t, emitContext, file, rec.output) }) } diff --git a/internal/transformers/esmodule.go b/internal/transformers/moduletransforms/esmodule.go similarity index 59% rename from internal/transformers/esmodule.go rename to internal/transformers/moduletransforms/esmodule.go index ad190af35f..3f1f90cdba 100644 --- a/internal/transformers/esmodule.go +++ b/internal/transformers/moduletransforms/esmodule.go @@ -1,4 +1,4 @@ -package transformers +package moduletransforms import ( "slices" @@ -7,10 +7,11 @@ import ( "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) type ESModuleTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions resolver binder.ReferenceResolver getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind @@ -24,7 +25,7 @@ type importRequireStatements struct { requireHelperName *ast.IdentifierNode } -func NewESModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *Transformer { +func NewESModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *transformers.Transformer { if resolver == nil { resolver = binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{}) } @@ -48,7 +49,7 @@ func (tx *ESModuleTransformer) visit(node *ast.Node) *ast.Node { case ast.KindCallExpression: node = tx.visitCallExpression(node.AsCallExpression()) default: - node = tx.visitor.VisitEachChild(node) + node = tx.Visitor().VisitEachChild(node) } return node } @@ -62,12 +63,12 @@ func (tx *ESModuleTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { tx.currentSourceFile = node tx.importRequireStatements = nil - result := tx.visitor.VisitEachChild(node.AsNode()).AsSourceFile() - tx.emitContext.AddEmitHelper(result.AsNode(), tx.emitContext.ReadEmitHelpers()...) + result := tx.Visitor().VisitEachChild(node.AsNode()).AsSourceFile() + tx.EmitContext().AddEmitHelper(result.AsNode(), tx.EmitContext().ReadEmitHelpers()...) - externalHelpersImportDeclaration := createExternalHelpersImportDeclarationIfNeeded(tx.emitContext, result, tx.compilerOptions, tx.getEmitModuleFormatOfFile(node), false /*hasExportStarsToExportValues*/, false /*hasImportStar*/, false /*hasImportDefault*/) + externalHelpersImportDeclaration := createExternalHelpersImportDeclarationIfNeeded(tx.EmitContext(), result, tx.compilerOptions, tx.getEmitModuleFormatOfFile(node), false /*hasExportStarsToExportValues*/, false /*hasImportStar*/, false /*hasImportDefault*/) if externalHelpersImportDeclaration != nil || tx.importRequireStatements != nil { - prologue, rest := tx.factory.SplitStandardPrologue(result.Statements.Nodes) + prologue, rest := tx.Factory().SplitStandardPrologue(result.Statements.Nodes) statements := slices.Clone(prologue) if externalHelpersImportDeclaration != nil { statements = append(statements, externalHelpersImportDeclaration) @@ -76,19 +77,19 @@ func (tx *ESModuleTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node { statements = append(statements, tx.importRequireStatements.statements...) } statements = append(statements, rest...) - statementList := tx.factory.NewNodeList(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = result.Statements.Loc - result = tx.factory.UpdateSourceFile(result, statementList).AsSourceFile() + result = tx.Factory().UpdateSourceFile(result, statementList).AsSourceFile() } if ast.IsExternalModule(result) && tx.compilerOptions.GetEmitModuleKind() != core.ModuleKindPreserve && !core.Some(result.Statements.Nodes, ast.IsExternalModuleIndicator) { statements := slices.Clone(result.Statements.Nodes) - statements = append(statements, createEmptyImports(tx.factory)) - statementList := tx.factory.NewNodeList(statements) + statements = append(statements, createEmptyImports(tx.Factory())) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = result.Statements.Loc - result = tx.factory.UpdateSourceFile(result, statementList).AsSourceFile() + result = tx.Factory().UpdateSourceFile(result, statementList).AsSourceFile() } tx.importRequireStatements = nil @@ -100,13 +101,13 @@ func (tx *ESModuleTransformer) visitImportDeclaration(node *ast.ImportDeclaratio if !tx.compilerOptions.RewriteRelativeImportExtensions.IsTrue() { return node.AsNode() } - updatedModuleSpecifier := rewriteModuleSpecifier(tx.emitContext, node.ModuleSpecifier, tx.compilerOptions) - return tx.factory.UpdateImportDeclaration( + updatedModuleSpecifier := rewriteModuleSpecifier(tx.EmitContext(), node.ModuleSpecifier, tx.compilerOptions) + return tx.Factory().UpdateImportDeclaration( node, nil, /*modifiers*/ - tx.visitor.VisitNode(node.ImportClause), + tx.Visitor().VisitNode(node.ImportClause), updatedModuleSpecifier, - tx.visitor.VisitNode(node.Attributes), + tx.Visitor().VisitNode(node.Attributes), ) } @@ -122,13 +123,13 @@ func (tx *ESModuleTransformer) visitImportEqualsDeclaration(node *ast.ImportEqua panic("import= for internal module references should be handled in an earlier transformer.") } - varStatement := tx.factory.NewVariableStatement( + varStatement := tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewVariableDeclaration( - node.Name().Clone(tx.factory), + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewVariableDeclaration( + node.Name().Clone(tx.Factory()), nil, /*exclamationToken*/ nil, /*type*/ tx.createRequireCall(node.AsNode()), @@ -136,26 +137,26 @@ func (tx *ESModuleTransformer) visitImportEqualsDeclaration(node *ast.ImportEqua }), ), ) - tx.emitContext.SetOriginal(varStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) + tx.EmitContext().SetOriginal(varStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) var statements []*ast.Statement statements = append(statements, varStatement) statements = tx.appendExportsOfImportEqualsDeclaration(statements, node) - return singleOrMany(statements, tx.factory) + return transformers.SingleOrMany(statements, tx.Factory()) } func (tx *ESModuleTransformer) appendExportsOfImportEqualsDeclaration(statements []*ast.Statement, node *ast.ImportEqualsDeclaration) []*ast.Statement { if ast.HasSyntacticModifier(node.AsNode(), ast.ModifierFlagsExport) { - statements = append(statements, tx.factory.NewExportDeclaration( + statements = append(statements, tx.Factory().NewExportDeclaration( nil, /*modifiers*/ false, /*isTypeOnly*/ - tx.factory.NewNamedExports( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewExportSpecifier( + tx.Factory().NewNamedExports( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewExportSpecifier( false, /*isTypeOnly*/ nil, /*propertyName*/ - node.Name().Clone(tx.factory), + node.Name().Clone(tx.Factory()), ), }), ), @@ -168,24 +169,24 @@ func (tx *ESModuleTransformer) appendExportsOfImportEqualsDeclaration(statements func (tx *ESModuleTransformer) visitExportAssignment(node *ast.ExportAssignment) *ast.Node { if !node.IsExportEquals { - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } if tx.compilerOptions.GetEmitModuleKind() != core.ModuleKindPreserve { // Elide `export=` as it is not legal with --module ES6 return nil } - statement := tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewIdentifier("module"), + statement := tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewIdentifier("module"), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("exports"), + tx.Factory().NewIdentifier("exports"), ast.NodeFlagsNone, ), - tx.visitor.VisitNode(node.Expression), + tx.Visitor().VisitNode(node.Expression), ), ) - tx.emitContext.SetOriginal(statement, node.AsNode()) + tx.EmitContext().SetOriginal(statement, node.AsNode()) return statement } @@ -194,51 +195,51 @@ func (tx *ESModuleTransformer) visitExportDeclaration(node *ast.ExportDeclaratio return node.AsNode() } - updatedModuleSpecifier := rewriteModuleSpecifier(tx.emitContext, node.ModuleSpecifier, tx.compilerOptions) + updatedModuleSpecifier := rewriteModuleSpecifier(tx.EmitContext(), node.ModuleSpecifier, tx.compilerOptions) if tx.compilerOptions.Module > core.ModuleKindES2015 || node.ExportClause == nil || !ast.IsNamespaceExport(node.ExportClause) { // Either ill-formed or don't need to be transformed. - return tx.factory.UpdateExportDeclaration( + return tx.Factory().UpdateExportDeclaration( node, nil, /*modifiers*/ false, /*isTypeOnly*/ node.ExportClause, updatedModuleSpecifier, - tx.visitor.VisitNode(node.Attributes), + tx.Visitor().VisitNode(node.Attributes), ) } oldIdentifier := node.ExportClause.Name() - synthName := tx.factory.NewGeneratedNameForNode(oldIdentifier) - importDecl := tx.factory.NewImportDeclaration( + synthName := tx.Factory().NewGeneratedNameForNode(oldIdentifier) + importDecl := tx.Factory().NewImportDeclaration( nil, /*modifiers*/ - tx.factory.NewImportClause( + tx.Factory().NewImportClause( false, /*isTypeOnly*/ nil, /*name*/ - tx.factory.NewNamespaceImport(synthName), + tx.Factory().NewNamespaceImport(synthName), ), updatedModuleSpecifier, - tx.visitor.VisitNode(node.Attributes), + tx.Visitor().VisitNode(node.Attributes), ) - tx.emitContext.SetOriginal(importDecl, node.ExportClause) + tx.EmitContext().SetOriginal(importDecl, node.ExportClause) var exportDecl *ast.Node if ast.IsExportNamespaceAsDefaultDeclaration(node.AsNode()) { - exportDecl = tx.factory.NewExportAssignment(nil /*modifiers*/, false /*isExportEquals*/, nil /*typeNode*/, synthName) + exportDecl = tx.Factory().NewExportAssignment(nil /*modifiers*/, false /*isExportEquals*/, nil /*typeNode*/, synthName) } else { - exportDecl = tx.factory.NewExportDeclaration( + exportDecl = tx.Factory().NewExportDeclaration( nil, /*modifiers*/ false, /*isTypeOnly*/ - tx.factory.NewNamedExports( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewExportSpecifier(false /*isTypeOnly*/, synthName, oldIdentifier), + tx.Factory().NewNamedExports( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewExportSpecifier(false /*isTypeOnly*/, synthName, oldIdentifier), }), ), nil, /*moduleSpecifier*/ nil, /*attributes*/ ) } - tx.emitContext.SetOriginal(exportDecl, node.AsNode()) - return singleOrMany([]*ast.Statement{importDecl, exportDecl}, tx.factory) + tx.EmitContext().SetOriginal(exportDecl, node.AsNode()) + return transformers.SingleOrMany([]*ast.Statement{importDecl, exportDecl}, tx.Factory()) } func (tx *ESModuleTransformer) visitCallExpression(node *ast.CallExpression) *ast.Node { @@ -248,32 +249,32 @@ func (tx *ESModuleTransformer) visitCallExpression(node *ast.CallExpression) *as return tx.visitImportOrRequireCall(node) } } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } func (tx *ESModuleTransformer) visitImportOrRequireCall(node *ast.CallExpression) *ast.Node { if len(node.Arguments.Nodes) == 0 { - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } - expression := tx.visitor.VisitNode(node.Expression) + expression := tx.Visitor().VisitNode(node.Expression) var argument *ast.Expression if ast.IsStringLiteralLike(node.Arguments.Nodes[0]) { - argument = rewriteModuleSpecifier(tx.emitContext, node.Arguments.Nodes[0], tx.compilerOptions) + argument = rewriteModuleSpecifier(tx.EmitContext(), node.Arguments.Nodes[0], tx.compilerOptions) } else { - argument = tx.factory.NewRewriteRelativeImportExtensionsHelper(node.Arguments.Nodes[0], tx.compilerOptions.Jsx == core.JsxEmitPreserve) + argument = tx.Factory().NewRewriteRelativeImportExtensionsHelper(node.Arguments.Nodes[0], tx.compilerOptions.Jsx == core.JsxEmitPreserve) } var arguments []*ast.Expression arguments = append(arguments, argument) - rest := core.FirstResult(tx.visitor.VisitSlice(node.Arguments.Nodes[1:])) + rest := core.FirstResult(tx.Visitor().VisitSlice(node.Arguments.Nodes[1:])) arguments = append(arguments, rest...) - argumentList := tx.factory.NewNodeList(arguments) + argumentList := tx.Factory().NewNodeList(arguments) argumentList.Loc = node.Arguments.Loc - return tx.factory.UpdateCallExpression( + return tx.Factory().UpdateCallExpression( node, expression, node.QuestionDotToken, @@ -283,64 +284,64 @@ func (tx *ESModuleTransformer) visitImportOrRequireCall(node *ast.CallExpression } func (tx *ESModuleTransformer) createRequireCall(node *ast.Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) *ast.Expression { - moduleName := getExternalModuleNameLiteral(tx.factory, node, tx.currentSourceFile, nil /*host*/, nil /*emitResolver*/, tx.compilerOptions) + moduleName := getExternalModuleNameLiteral(tx.Factory(), node, tx.currentSourceFile, nil /*host*/, nil /*emitResolver*/, tx.compilerOptions) var args []*ast.Expression if moduleName != nil { - args = append(args, rewriteModuleSpecifier(tx.emitContext, moduleName, tx.compilerOptions)) + args = append(args, rewriteModuleSpecifier(tx.EmitContext(), moduleName, tx.compilerOptions)) } if tx.compilerOptions.GetEmitModuleKind() == core.ModuleKindPreserve { - return tx.factory.NewCallExpression( - tx.factory.NewIdentifier("require"), + return tx.Factory().NewCallExpression( + tx.Factory().NewIdentifier("require"), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList(args), + tx.Factory().NewNodeList(args), ast.NodeFlagsNone, ) } if tx.importRequireStatements == nil { - createRequireName := tx.factory.NewUniqueNameEx("_createRequire", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel}) - importStatement := tx.factory.NewImportDeclaration( + createRequireName := tx.Factory().NewUniqueNameEx("_createRequire", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel}) + importStatement := tx.Factory().NewImportDeclaration( nil, /*modifiers*/ - tx.factory.NewImportClause( + tx.Factory().NewImportClause( false, /*isTypeOnly*/ nil, /*name*/ - tx.factory.NewNamedImports( - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewImportSpecifier( + tx.Factory().NewNamedImports( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewImportSpecifier( false, /*isTypeOnly*/ - tx.factory.NewIdentifier("createRequire"), + tx.Factory().NewIdentifier("createRequire"), createRequireName, ), }), ), ), - tx.factory.NewStringLiteral("module"), + tx.Factory().NewStringLiteral("module"), nil, /*attributes*/ ) - tx.emitContext.AddEmitFlags(importStatement, printer.EFCustomPrologue) + tx.EmitContext().AddEmitFlags(importStatement, printer.EFCustomPrologue) - requireHelperName := tx.factory.NewUniqueNameEx("__require", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel}) - requireStatement := tx.factory.NewVariableStatement( + requireHelperName := tx.Factory().NewUniqueNameEx("__require", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel}) + requireStatement := tx.Factory().NewVariableStatement( nil, /*modifiers*/ - tx.factory.NewVariableDeclarationList( + tx.Factory().NewVariableDeclarationList( ast.NodeFlagsConst, - tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewVariableDeclaration( + tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewVariableDeclaration( requireHelperName, nil, /*exclamationToken*/ nil, /*type*/ - tx.factory.NewCallExpression( - createRequireName.Clone(tx.factory), + tx.Factory().NewCallExpression( + createRequireName.Clone(tx.Factory()), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList([]*ast.Expression{ - tx.factory.NewPropertyAccessExpression( - tx.factory.NewMetaProperty(ast.KindImportKeyword, tx.factory.NewIdentifier("meta")), + tx.Factory().NewNodeList([]*ast.Expression{ + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewMetaProperty(ast.KindImportKeyword, tx.Factory().NewIdentifier("meta")), nil, /*questionDotToken*/ - tx.factory.NewIdentifier("url"), + tx.Factory().NewIdentifier("url"), ast.NodeFlagsNone, ), }), @@ -350,18 +351,18 @@ func (tx *ESModuleTransformer) createRequireCall(node *ast.Node /*ImportDeclarat }), ), ) - tx.emitContext.AddEmitFlags(requireStatement, printer.EFCustomPrologue) + tx.EmitContext().AddEmitFlags(requireStatement, printer.EFCustomPrologue) tx.importRequireStatements = &importRequireStatements{ statements: []*ast.Statement{importStatement, requireStatement}, requireHelperName: requireHelperName, } } - return tx.factory.NewCallExpression( - tx.importRequireStatements.requireHelperName.Clone(tx.factory), + return tx.Factory().NewCallExpression( + tx.importRequireStatements.requireHelperName.Clone(tx.Factory()), nil, /*questionDotToken*/ nil, /*typeArguments*/ - tx.factory.NewNodeList(args), + tx.Factory().NewNodeList(args), ast.NodeFlagsNone, ) } diff --git a/internal/transformers/esmodule_test.go b/internal/transformers/moduletransforms/esmodule_test.go similarity index 94% rename from internal/transformers/esmodule_test.go rename to internal/transformers/moduletransforms/esmodule_test.go index 7c7c38b58f..bb41650f10 100644 --- a/internal/transformers/esmodule_test.go +++ b/internal/transformers/moduletransforms/esmodule_test.go @@ -1,4 +1,4 @@ -package transformers +package moduletransforms_test import ( "testing" @@ -9,6 +9,8 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" + "github.com/microsoft/typescript-go/internal/transformers/moduletransforms" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" ) func TestESModuleTransformer(t *testing.T) { @@ -238,8 +240,8 @@ var __rewriteRelativeImportExtension;`, emitContext := printer.NewEmitContext() resolver := binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{}) - file = NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file) - file = NewESModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file) + file = tstransforms.NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file) + file = moduletransforms.NewESModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file) emittestutil.CheckEmit(t, emitContext, file, rec.output) }) } diff --git a/internal/transformers/externalmoduleinfo.go b/internal/transformers/moduletransforms/externalmoduleinfo.go similarity index 99% rename from internal/transformers/externalmoduleinfo.go rename to internal/transformers/moduletransforms/externalmoduleinfo.go index 1845325522..382aa91c62 100644 --- a/internal/transformers/externalmoduleinfo.go +++ b/internal/transformers/moduletransforms/externalmoduleinfo.go @@ -1,4 +1,4 @@ -package transformers +package moduletransforms import ( "slices" @@ -9,6 +9,7 @@ import ( "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/stringutil" + "github.com/microsoft/typescript-go/internal/transformers" ) type externalModuleInfo struct { @@ -237,7 +238,7 @@ func (c *externalModuleInfoCollector) collectExportedVariableInfo(decl *ast.Node text := decl.Name().Text() if c.addUniqueExport(text) { c.addExportedName(decl.Name()) - if isLocalName(c.emitContext, decl.Name()) { + if transformers.IsLocalName(c.emitContext, decl.Name()) { c.addExportedBinding(decl, decl.Name()) } } diff --git a/internal/transformers/impliedmodule.go b/internal/transformers/moduletransforms/impliedmodule.go similarity index 73% rename from internal/transformers/impliedmodule.go rename to internal/transformers/moduletransforms/impliedmodule.go index 0ace66e810..8ad007e6a5 100644 --- a/internal/transformers/impliedmodule.go +++ b/internal/transformers/moduletransforms/impliedmodule.go @@ -1,22 +1,23 @@ -package transformers +package moduletransforms import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) type ImpliedModuleTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions resolver binder.ReferenceResolver getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind - cjsTransformer *Transformer - esmTransformer *Transformer + cjsTransformer *transformers.Transformer + esmTransformer *transformers.Transformer } -func NewImpliedModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *Transformer { +func NewImpliedModuleTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *transformers.Transformer { if resolver == nil { resolver = binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{}) } @@ -39,15 +40,15 @@ func (tx *ImpliedModuleTransformer) visitSourceFile(node *ast.SourceFile) *ast.N format := tx.getEmitModuleFormatOfFile(node) - var transformer *Transformer + var transformer *transformers.Transformer if format >= core.ModuleKindES2015 { if tx.esmTransformer == nil { - tx.esmTransformer = NewESModuleTransformer(tx.emitContext, tx.compilerOptions, tx.resolver, tx.getEmitModuleFormatOfFile) + tx.esmTransformer = NewESModuleTransformer(tx.EmitContext(), tx.compilerOptions, tx.resolver, tx.getEmitModuleFormatOfFile) } transformer = tx.esmTransformer } else { if tx.cjsTransformer == nil { - tx.cjsTransformer = NewCommonJSModuleTransformer(tx.emitContext, tx.compilerOptions, tx.resolver, tx.getEmitModuleFormatOfFile) + tx.cjsTransformer = NewCommonJSModuleTransformer(tx.EmitContext(), tx.compilerOptions, tx.resolver, tx.getEmitModuleFormatOfFile) } transformer = tx.cjsTransformer } diff --git a/internal/transformers/moduletransforms/utilities.go b/internal/transformers/moduletransforms/utilities.go new file mode 100644 index 0000000000..c55804591a --- /dev/null +++ b/internal/transformers/moduletransforms/utilities.go @@ -0,0 +1,132 @@ +package moduletransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/outputpaths" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/tspath" +) + +func isDeclarationNameOfEnumOrNamespace(emitContext *printer.EmitContext, node *ast.IdentifierNode) bool { + if original := emitContext.MostOriginal(node); original != nil && original.Parent != nil { + switch original.Parent.Kind { + case ast.KindEnumDeclaration, ast.KindModuleDeclaration: + return original == original.Parent.Name() + } + } + return false +} + +func rewriteModuleSpecifier(emitContext *printer.EmitContext, node *ast.Expression, compilerOptions *core.CompilerOptions) *ast.Expression { + if node == nil || !ast.IsStringLiteral(node) || !core.ShouldRewriteModuleSpecifier(node.Text(), compilerOptions) { + return node + } + updatedText := tspath.ChangeExtension(node.Text(), outputpaths.GetOutputExtension(node.Text(), compilerOptions.Jsx)) + if updatedText != node.Text() { + updated := emitContext.Factory.NewStringLiteral(updatedText) + // !!! set quote style + emitContext.SetOriginal(updated, node) + emitContext.AssignCommentAndSourceMapRanges(updated, node) + return updated + } + return node +} + +func createEmptyImports(factory *printer.NodeFactory) *ast.Statement { + return factory.NewExportDeclaration( + nil, /*modifiers*/ + false, /*isTypeOnly*/ + factory.NewNamedExports(factory.NewNodeList(nil)), + nil, /*moduleSpecifier*/ + nil, /*attributes*/ + ) +} + +// Get the name of a target module from an import/export declaration as should be written in the emitted output. +// The emitted output name can be different from the input if: +// 1. The module has a /// +// 2. --out or --outFile is used, making the name relative to the rootDir +// 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). +// +// Otherwise, a new StringLiteral node representing the module name will be returned. +func getExternalModuleNameLiteral(factory *printer.NodeFactory, importNode *ast.Node /*ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall*/, sourceFile *ast.SourceFile, host any /*EmitHost*/, resolver printer.EmitResolver, compilerOptions *core.CompilerOptions) *ast.StringLiteralNode { + moduleName := ast.GetExternalModuleName(importNode) + if moduleName != nil && ast.IsStringLiteral(moduleName) { + name := tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) + if name == nil { + name = tryRenameExternalModule(factory, moduleName, sourceFile) + } + if name == nil { + name = factory.NewStringLiteral(moduleName.Text()) + } + return name + } + return nil +} + +// Get the name of a module as should be written in the emitted output. +// The emitted output name can be different from the input if: +// 1. The module has a /// +// 2. --out or --outFile is used, making the name relative to the rootDir +// +// Otherwise, a new StringLiteral node representing the module name will be returned. +func tryGetModuleNameFromFile(factory *printer.NodeFactory, file *ast.SourceFile, host any /*EmitHost*/, options *core.CompilerOptions) *ast.StringLiteralNode { + if file == nil { + return nil + } + // !!! + // if file.moduleName { + // return factory.createStringLiteral(file.moduleName) + // } + if !file.IsDeclarationFile && len(options.OutFile) > 0 { + return factory.NewStringLiteral(getExternalModuleNameFromPath(host, file.FileName(), "" /*referencePath*/)) + } + return nil +} + +func tryGetModuleNameFromDeclaration(declaration *ast.Node /*ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall*/, host any /*EmitHost*/, factory *printer.NodeFactory, resolver printer.EmitResolver, compilerOptions *core.CompilerOptions) *ast.StringLiteralNode { + if resolver == nil { + return nil + } + return tryGetModuleNameFromFile(factory, resolver.GetExternalModuleFileFromDeclaration(declaration), host, compilerOptions) +} + +// Resolves a local path to a path which is absolute to the base of the emit +func getExternalModuleNameFromPath(host any /*ResolveModuleNameResolutionHost*/, fileName string, referencePath string) string { + // !!! + return "" +} + +// Some bundlers (SystemJS builder) sometimes want to rename dependencies. +// Here we check if alternative name was provided for a given moduleName and return it if possible. +func tryRenameExternalModule(factory *printer.NodeFactory, moduleName *ast.LiteralExpression, sourceFile *ast.SourceFile) *ast.StringLiteralNode { + // !!! + return nil +} + +func isFileLevelReservedGeneratedIdentifier(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { + info := emitContext.GetAutoGenerateInfo(name) + return info != nil && + info.Flags.IsFileLevel() && + info.Flags.IsOptimistic() && + info.Flags.IsReservedInNestedScopes() +} + +// Used in the module transformer to check if an expression is reasonably without sideeffect, +// +// and thus better to copy into multiple places rather than to cache in a temporary variable +// - this is mostly subjective beyond the requirement that the expression not be sideeffecting +func isSimpleCopiableExpression(expression *ast.Expression) bool { + return ast.IsStringLiteralLike(expression) || + ast.IsNumericLiteral(expression) || + ast.IsKeywordKind(expression.Kind) || + ast.IsIdentifier(expression) +} + +// A simple inlinable expression is an expression which can be copied into multiple locations +// without risk of repeating any sideeffects and whose value could not possibly change between +// any such locations +func isSimpleInlineableExpression(expression *ast.Expression) bool { + return !ast.IsIdentifier(expression) && isSimpleCopiableExpression(expression) +} diff --git a/internal/transformers/transformer.go b/internal/transformers/transformer.go index 5ff107e250..da7bece127 100644 --- a/internal/transformers/transformer.go +++ b/internal/transformers/transformer.go @@ -2,8 +2,6 @@ package transformers import ( "github.com/microsoft/typescript-go/internal/ast" - "github.com/microsoft/typescript-go/internal/binder" - "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" ) @@ -41,74 +39,3 @@ func (tx *Transformer) Factory() *printer.NodeFactory { func (tx *Transformer) TransformSourceFile(file *ast.SourceFile) *ast.SourceFile { return tx.visitor.VisitSourceFile(file) } - -func getModuleTransformer(emitContext *printer.EmitContext, options *core.CompilerOptions, resolver binder.ReferenceResolver, getEmitModuleFormatOfFile func(file ast.HasFileName) core.ModuleKind) *Transformer { - switch options.GetEmitModuleKind() { - case core.ModuleKindPreserve: - // `ESModuleTransformer` contains logic for preserving CJS input syntax in `--module preserve` - return NewESModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) - - case core.ModuleKindESNext, - core.ModuleKindES2022, - core.ModuleKindES2020, - core.ModuleKindES2015, - core.ModuleKindNode18, - core.ModuleKindNode16, - core.ModuleKindNodeNext, - core.ModuleKindCommonJS: - return NewImpliedModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) - - default: - return NewCommonJSModuleTransformer(emitContext, options, resolver, getEmitModuleFormatOfFile) - } -} - -func GetScriptTransformers(emitContext *printer.EmitContext, host printer.EmitHost, sourceFile *ast.SourceFile) []*Transformer { - var tx []*Transformer - options := host.Options() - languageVersion := options.GetEmitScriptTarget() - - // JS files don't use reference calculations as they don't do import elision, no need to calculate it - importElisionEnabled := !options.VerbatimModuleSyntax.IsTrue() && !ast.IsInJSFile(sourceFile.AsNode()) - - var emitResolver printer.EmitResolver - var referenceResolver binder.ReferenceResolver - if importElisionEnabled || options.GetJSXTransformEnabled() { - emitResolver = host.GetEmitResolver(sourceFile, false /*skipDiagnostics*/) // !!! conditionally skip diagnostics - emitResolver.MarkLinkedReferencesRecursively(sourceFile) - referenceResolver = emitResolver - } else { - referenceResolver = binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{}) - } - - // transform TypeScript syntax - { - // erase types - tx = append(tx, NewTypeEraserTransformer(emitContext, options)) - - // elide imports - if importElisionEnabled { - tx = append(tx, NewImportElisionTransformer(emitContext, options, emitResolver)) - } - - // transform `enum`, `namespace`, and parameter properties - tx = append(tx, NewRuntimeSyntaxTransformer(emitContext, options, referenceResolver)) - } - - // !!! transform legacy decorator syntax - if options.GetJSXTransformEnabled() { - tx = append(tx, NewJSXTransformer(emitContext, options, emitResolver)) - } - - if languageVersion < core.ScriptTargetESNext { - tx = append(tx, NewESNextTransformer(emitContext)) - } - - // !!! transform native decorator syntax - // !!! transform class field syntax - // !!! transform other language targets - - // transform module syntax - tx = append(tx, getModuleTransformer(emitContext, options, referenceResolver, host.GetEmitModuleFormatOfFile)) - return tx -} diff --git a/internal/transformers/importelision.go b/internal/transformers/tstransforms/importelision.go similarity index 82% rename from internal/transformers/importelision.go rename to internal/transformers/tstransforms/importelision.go index 57678a09d2..d13bddaba2 100644 --- a/internal/transformers/importelision.go +++ b/internal/transformers/tstransforms/importelision.go @@ -1,19 +1,20 @@ -package transformers +package tstransforms import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) type ImportElisionTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions currentSourceFile *ast.SourceFile emitResolver printer.EmitResolver } -func NewImportElisionTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver printer.EmitResolver) *Transformer { +func NewImportElisionTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver printer.EmitResolver) *transformers.Transformer { if compilerOptions.VerbatimModuleSyntax.IsTrue() { panic("ImportElisionTransformer should not be used with VerbatimModuleSyntax") } @@ -27,30 +28,30 @@ func (tx *ImportElisionTransformer) visit(node *ast.Node) *ast.Node { if !tx.isElisionBlocked(node) && !tx.shouldEmitImportEqualsDeclaration(node.AsImportEqualsDeclaration()) { return nil } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindImportDeclaration: if !tx.isElisionBlocked(node) { n := node.AsImportDeclaration() // Do not elide a side-effect only import declaration. // import "foo"; if n.ImportClause != nil { - importClause := tx.visitor.VisitNode(n.ImportClause) + importClause := tx.Visitor().VisitNode(n.ImportClause) if importClause == nil { return nil } - return tx.factory.UpdateImportDeclaration(n, n.Modifiers(), importClause, n.ModuleSpecifier, tx.visitor.VisitNode(n.Attributes)) + return tx.Factory().UpdateImportDeclaration(n, n.Modifiers(), importClause, n.ModuleSpecifier, tx.Visitor().VisitNode(n.Attributes)) } } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindImportClause: n := node.AsImportClause() name := core.IfElse(tx.shouldEmitAliasDeclaration(node), n.Name(), nil) - namedBindings := tx.visitor.VisitNode(n.NamedBindings) + namedBindings := tx.Visitor().VisitNode(n.NamedBindings) if name == nil && namedBindings == nil { // all import bindings were elided return nil } - return tx.factory.UpdateImportClause(n, false /*isTypeOnly*/, name, namedBindings) + return tx.Factory().UpdateImportClause(n, false /*isTypeOnly*/, name, namedBindings) case ast.KindNamespaceImport: if !tx.shouldEmitAliasDeclaration(node) { // elide unused imports @@ -59,12 +60,12 @@ func (tx *ImportElisionTransformer) visit(node *ast.Node) *ast.Node { return node case ast.KindNamedImports: n := node.AsNamedImports() - elements := tx.visitor.VisitNodes(n.Elements) + elements := tx.Visitor().VisitNodes(n.Elements) if len(elements.Nodes) == 0 { // all import specifiers were elided return nil } - return tx.factory.UpdateNamedImports(n, elements) + return tx.Factory().UpdateNamedImports(n, elements) case ast.KindImportSpecifier: if !tx.shouldEmitAliasDeclaration(node) { // elide type-only or unused imports @@ -76,29 +77,29 @@ func (tx *ImportElisionTransformer) visit(node *ast.Node) *ast.Node { // elide unused import return nil } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindExportDeclaration: if !tx.isElisionBlocked(node) { n := node.AsExportDeclaration() var exportClause *ast.Node if n.ExportClause != nil { - exportClause = tx.visitor.VisitNode(n.ExportClause) + exportClause = tx.Visitor().VisitNode(n.ExportClause) if exportClause == nil { // all export bindings were elided return nil } } - return tx.factory.UpdateExportDeclaration(n, nil /*modifiers*/, false /*isTypeOnly*/, exportClause, tx.visitor.VisitNode(n.ModuleSpecifier), tx.visitor.VisitNode(n.Attributes)) + return tx.Factory().UpdateExportDeclaration(n, nil /*modifiers*/, false /*isTypeOnly*/, exportClause, tx.Visitor().VisitNode(n.ModuleSpecifier), tx.Visitor().VisitNode(n.Attributes)) } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindNamedExports: n := node.AsNamedExports() - elements := tx.visitor.VisitNodes(n.Elements) + elements := tx.Visitor().VisitNodes(n.Elements) if len(elements.Nodes) == 0 { // all export specifiers were elided return nil } - return tx.factory.UpdateNamedExports(n, elements) + return tx.Factory().UpdateNamedExports(n, elements) case ast.KindExportSpecifier: if !tx.isValueAliasDeclaration(node) { // elide unused export @@ -108,7 +109,7 @@ func (tx *ImportElisionTransformer) visit(node *ast.Node) *ast.Node { case ast.KindSourceFile: savedCurrentSourceFile := tx.currentSourceFile tx.currentSourceFile = node.AsSourceFile() - node = tx.visitor.VisitEachChild(node) + node = tx.Visitor().VisitEachChild(node) tx.currentSourceFile = savedCurrentSourceFile return node default: @@ -134,17 +135,17 @@ func (tx *ImportElisionTransformer) shouldEmitImportEqualsDeclaration(node *ast. } func (tx *ImportElisionTransformer) isReferencedAliasDeclaration(node *ast.Node) bool { - node = tx.emitContext.ParseNode(node) + node = tx.EmitContext().ParseNode(node) return node == nil || tx.emitResolver.IsReferencedAliasDeclaration(node) } func (tx *ImportElisionTransformer) isValueAliasDeclaration(node *ast.Node) bool { - node = tx.emitContext.ParseNode(node) + node = tx.EmitContext().ParseNode(node) return node == nil || tx.emitResolver.IsValueAliasDeclaration(node) } func (tx *ImportElisionTransformer) isTopLevelValueImportEqualsWithEntityName(node *ast.Node) bool { - node = tx.emitContext.ParseNode(node) + node = tx.EmitContext().ParseNode(node) return node != nil && tx.emitResolver.IsTopLevelValueImportEqualsWithEntityName(node) } @@ -155,7 +156,7 @@ func (tx *ImportElisionTransformer) isTopLevelValueImportEqualsWithEntityName(no // transform, although we will continue to allow it if the statement hasn't replaced a node of a different kind and // as long as the local bindings for the declarations are unchanged. func (tx *ImportElisionTransformer) isElisionBlocked(node *ast.Node /*ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration*/) bool { - parsed := tx.emitContext.ParseNode(node) + parsed := tx.EmitContext().ParseNode(node) if parsed == node || ast.IsExportAssignment(node) { return false } diff --git a/internal/transformers/importelision_test.go b/internal/transformers/tstransforms/importelision_test.go similarity index 96% rename from internal/transformers/importelision_test.go rename to internal/transformers/tstransforms/importelision_test.go index c46aa9e037..7c2511c238 100644 --- a/internal/transformers/importelision_test.go +++ b/internal/transformers/tstransforms/importelision_test.go @@ -1,4 +1,4 @@ -package transformers +package tstransforms_test import ( "testing" @@ -12,6 +12,7 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" "github.com/microsoft/typescript-go/internal/tsoptions" "github.com/microsoft/typescript-go/internal/tspath" ) @@ -240,8 +241,8 @@ func TestImportElision(t *testing.T) { emitResolver.MarkLinkedReferencesRecursively(file) emitContext := printer.NewEmitContext() - file = NewTypeEraserTransformer(emitContext, compilerOptions).TransformSourceFile(file) - file = NewImportElisionTransformer(emitContext, compilerOptions, emitResolver).TransformSourceFile(file) + file = tstransforms.NewTypeEraserTransformer(emitContext, compilerOptions).TransformSourceFile(file) + file = tstransforms.NewImportElisionTransformer(emitContext, compilerOptions, emitResolver).TransformSourceFile(file) emittestutil.CheckEmit(t, nil, file, rec.output) }) } diff --git a/internal/transformers/runtimesyntax.go b/internal/transformers/tstransforms/runtimesyntax.go similarity index 69% rename from internal/transformers/runtimesyntax.go rename to internal/transformers/tstransforms/runtimesyntax.go index caa3eed6c9..4c994085fd 100644 --- a/internal/transformers/runtimesyntax.go +++ b/internal/transformers/tstransforms/runtimesyntax.go @@ -1,4 +1,4 @@ -package transformers +package tstransforms // !!! Unqualified enum member references across merged enum declarations are not currently supported (e.g `enum E {A}; enum E {B=A}`) // !!! Unqualified namespace member references across merged namespace declarations are not currently supported (e.g `namespace N { export var x = 1; }; namespace N { x; }`). @@ -13,11 +13,12 @@ import ( "github.com/microsoft/typescript-go/internal/evaluator" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) // Transforms TypeScript-specific runtime syntax into JavaScript-compatible syntax. type RuntimeSyntaxTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions parentNode *ast.Node currentNode *ast.Node @@ -31,7 +32,7 @@ type RuntimeSyntaxTransformer struct { enumMemberCache map[*ast.EnumDeclarationNode]map[string]evaluator.Result } -func NewRuntimeSyntaxTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver) *Transformer { +func NewRuntimeSyntaxTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions, resolver binder.ReferenceResolver) *transformers.Transformer { tx := &RuntimeSyntaxTransformer{compilerOptions: compilerOptions, resolver: resolver} return tx.NewTransformer(tx.visit, emitContext) } @@ -117,7 +118,7 @@ func (tx *RuntimeSyntaxTransformer) visit(node *ast.Node) *ast.Node { case ast.KindShorthandPropertyAssignment: node = tx.visitShorthandPropertyAssignment(node.AsShorthandPropertyAssignment()) default: - node = tx.visitor.VisitEachChild(node) + node = tx.Visitor().VisitEachChild(node) } return node } @@ -180,17 +181,17 @@ func (tx *RuntimeSyntaxTransformer) getExpressionForPropertyName(member *ast.Enu name := member.Name() switch name.Kind { case ast.KindPrivateIdentifier: - return tx.factory.NewIdentifier("") + return tx.Factory().NewIdentifier("") case ast.KindComputedPropertyName: n := name.AsComputedPropertyName() // enums don't support computed properties so we always generate the 'expression' part of the name as-is. - return tx.visitor.VisitNode(n.Expression) + return tx.Visitor().VisitNode(n.Expression) case ast.KindIdentifier: - return tx.factory.NewStringLiteralFromNode(name) + return tx.Factory().NewStringLiteralFromNode(name) case ast.KindStringLiteral: - return tx.factory.NewStringLiteral(name.AsStringLiteral().Text) + return tx.Factory().NewStringLiteral(name.AsStringLiteral().Text) case ast.KindNumericLiteral: - return tx.factory.NewNumericLiteral(name.AsNumericLiteral().Text) + return tx.Factory().NewNumericLiteral(name.AsNumericLiteral().Text) default: return name } @@ -207,38 +208,38 @@ func (tx *RuntimeSyntaxTransformer) getEnumQualifiedReference(enum *ast.EnumDecl // Gets an expression like `E.A` that references an enum member. func (tx *RuntimeSyntaxTransformer) getEnumQualifiedProperty(enum *ast.EnumDeclaration, member *ast.EnumMember) *ast.Expression { - prop := tx.getNamespaceQualifiedProperty(tx.getNamespaceContainerName(enum.AsNode()), member.Name().Clone(tx.factory)) - tx.emitContext.AddEmitFlags(prop, printer.EFNoComments|printer.EFNoNestedComments|printer.EFNoSourceMap|printer.EFNoNestedSourceMaps) + prop := tx.getNamespaceQualifiedProperty(tx.getNamespaceContainerName(enum.AsNode()), member.Name().Clone(tx.Factory())) + tx.EmitContext().AddEmitFlags(prop, printer.EFNoComments|printer.EFNoNestedComments|printer.EFNoSourceMap|printer.EFNoNestedSourceMaps) return prop } // Gets an expression like `E["A"]` that references an enum member. func (tx *RuntimeSyntaxTransformer) getEnumQualifiedElement(enum *ast.EnumDeclaration, member *ast.EnumMember) *ast.Expression { prop := tx.getNamespaceQualifiedElement(tx.getNamespaceContainerName(enum.AsNode()), tx.getExpressionForPropertyName(member)) - tx.emitContext.AddEmitFlags(prop, printer.EFNoComments|printer.EFNoNestedComments|printer.EFNoSourceMap|printer.EFNoNestedSourceMaps) + tx.EmitContext().AddEmitFlags(prop, printer.EFNoComments|printer.EFNoNestedComments|printer.EFNoSourceMap|printer.EFNoNestedSourceMaps) return prop } // Gets an expression used to refer to a namespace or enum from within the body of its declaration. func (tx *RuntimeSyntaxTransformer) getNamespaceContainerName(node *ast.Node) *ast.IdentifierNode { - return tx.factory.NewGeneratedNameForNode(node) + return tx.Factory().NewGeneratedNameForNode(node) } // Gets an expression used to refer to an export of a namespace or a member of an enum by property name. func (tx *RuntimeSyntaxTransformer) getNamespaceQualifiedProperty(ns *ast.IdentifierNode, name *ast.IdentifierNode) *ast.Expression { - return tx.factory.GetNamespaceMemberName(ns, name, printer.NameOptions{AllowSourceMaps: true}) + return tx.Factory().GetNamespaceMemberName(ns, name, printer.NameOptions{AllowSourceMaps: true}) } // Gets an expression used to refer to an export of a namespace or a member of an enum by indexed access. func (tx *RuntimeSyntaxTransformer) getNamespaceQualifiedElement(ns *ast.IdentifierNode, expression *ast.Expression) *ast.Expression { - qualifiedName := tx.emitContext.Factory.NewElementAccessExpression(ns, nil /*questionDotToken*/, expression, ast.NodeFlagsNone) - tx.emitContext.AssignCommentAndSourceMapRanges(qualifiedName, expression) + qualifiedName := tx.EmitContext().Factory.NewElementAccessExpression(ns, nil /*questionDotToken*/, expression, ast.NodeFlagsNone) + tx.EmitContext().AssignCommentAndSourceMapRanges(qualifiedName, expression) return qualifiedName } // Gets an expression used within the provided node's container for any exported references. func (tx *RuntimeSyntaxTransformer) getExportQualifiedReferenceToDeclaration(node *ast.Declaration) *ast.Expression { - exportName := tx.factory.GetDeclarationNameEx(node.AsNode(), printer.NameOptions{AllowSourceMaps: true}) + exportName := tx.Factory().GetDeclarationNameEx(node.AsNode(), printer.NameOptions{AllowSourceMaps: true}) if tx.isExportOfNamespace(node.AsNode()) { return tx.getNamespaceQualifiedProperty(tx.getNamespaceContainerName(tx.currentNamespace), exportName) } @@ -253,14 +254,14 @@ func (tx *RuntimeSyntaxTransformer) addVarForDeclaration(statements []*ast.State if tx.isExportOfExternalModule(node) { // export { name }; - statements = append(statements, tx.factory.NewExportDeclaration( + statements = append(statements, tx.Factory().NewExportDeclaration( nil, /*modifiers*/ false, /*isTypeOnly*/ - tx.factory.NewNamedExports(tx.factory.NewNodeList([]*ast.Node{ - tx.factory.NewExportSpecifier( + tx.Factory().NewNamedExports(tx.Factory().NewNodeList([]*ast.Node{ + tx.Factory().NewExportSpecifier( false, /*isTypeOnly*/ nil, /*propertyName*/ - node.Name().Clone(tx.factory), + node.Name().Clone(tx.Factory()), ), })), nil, /*moduleSpecifier*/ @@ -269,18 +270,18 @@ func (tx *RuntimeSyntaxTransformer) addVarForDeclaration(statements []*ast.State } // var name; - name := tx.factory.GetLocalNameEx(node, printer.AssignedNameOptions{AllowSourceMaps: true}) - varDecl := tx.factory.NewVariableDeclaration(name, nil, nil, nil) + name := tx.Factory().GetLocalNameEx(node, printer.AssignedNameOptions{AllowSourceMaps: true}) + varDecl := tx.Factory().NewVariableDeclaration(name, nil, nil, nil) varFlags := core.IfElse(tx.currentScope == tx.currentSourceFile, ast.NodeFlagsNone, ast.NodeFlagsLet) - varDecls := tx.factory.NewVariableDeclarationList(varFlags, tx.factory.NewNodeList([]*ast.Node{varDecl})) - varStatement := tx.factory.NewVariableStatement(nil /*modifiers*/, varDecls) + varDecls := tx.Factory().NewVariableDeclarationList(varFlags, tx.Factory().NewNodeList([]*ast.Node{varDecl})) + varStatement := tx.Factory().NewVariableStatement(nil /*modifiers*/, varDecls) - tx.emitContext.SetOriginal(varDecl, node) + tx.EmitContext().SetOriginal(varDecl, node) // !!! synthetic comments - tx.emitContext.SetOriginal(varStatement, node) + tx.EmitContext().SetOriginal(varStatement, node) // Adjust the source map emit to match the old emitter. - tx.emitContext.SetSourceMapRange(varDecls, node.Loc) + tx.EmitContext().SetSourceMapRange(varDecls, node.Loc) // Trailing comments for enum declaration should be emitted after the function closure // instead of the variable statement: @@ -298,8 +299,8 @@ func (tx *RuntimeSyntaxTransformer) addVarForDeclaration(statements []*ast.State // E[E["A"] = 0] = "A"; // })(E || (E = {})); // trailing comment // - tx.emitContext.SetCommentRange(varStatement, node.Loc) - tx.emitContext.AddEmitFlags(varStatement, printer.EFNoTrailingComments) + tx.EmitContext().SetCommentRange(varStatement, node.Loc) + tx.EmitContext().AddEmitFlags(varStatement, printer.EFNoTrailingComments) statements = append(statements, varStatement) return statements, true @@ -321,35 +322,35 @@ func (tx *RuntimeSyntaxTransformer) visitEnumDeclaration(node *ast.EnumDeclarati // x || (x = {}) // exports.x || (exports.x = {}) - enumArg := tx.factory.NewLogicalORExpression( + enumArg := tx.Factory().NewLogicalORExpression( tx.getExportQualifiedReferenceToDeclaration(node.AsNode()), - tx.factory.NewAssignmentExpression( + tx.Factory().NewAssignmentExpression( tx.getExportQualifiedReferenceToDeclaration(node.AsNode()), - tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{}), false), + tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{}), false), ), ) if tx.isExportOfNamespace(node.AsNode()) { // `localName` is the expression used within this node's containing scope for any local references. - localName := tx.factory.GetLocalNameEx(node.AsNode(), printer.AssignedNameOptions{AllowSourceMaps: true}) + localName := tx.Factory().GetLocalNameEx(node.AsNode(), printer.AssignedNameOptions{AllowSourceMaps: true}) // x = (exports.x || (exports.x = {})) - enumArg = tx.factory.NewAssignmentExpression(localName, enumArg) + enumArg = tx.Factory().NewAssignmentExpression(localName, enumArg) } // (function (name) { ... })(name || (name = {})) - enumParamName := tx.factory.NewGeneratedNameForNode(node.AsNode()) - tx.emitContext.SetSourceMapRange(enumParamName, node.Name().Loc) + enumParamName := tx.Factory().NewGeneratedNameForNode(node.AsNode()) + tx.EmitContext().SetSourceMapRange(enumParamName, node.Name().Loc) - enumParam := tx.factory.NewParameterDeclaration(nil, nil, enumParamName, nil, nil, nil) + enumParam := tx.Factory().NewParameterDeclaration(nil, nil, enumParamName, nil, nil, nil) enumBody := tx.transformEnumBody(node) - enumFunc := tx.factory.NewFunctionExpression(nil, nil, nil, nil, tx.factory.NewNodeList([]*ast.Node{enumParam}), nil, enumBody) - enumCall := tx.factory.NewCallExpression(tx.factory.NewParenthesizedExpression(enumFunc), nil, nil, tx.factory.NewNodeList([]*ast.Node{enumArg}), ast.NodeFlagsNone) - enumStatement := tx.factory.NewExpressionStatement(enumCall) - tx.emitContext.SetOriginal(enumStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(enumStatement, node.AsNode()) - tx.emitContext.AddEmitFlags(enumStatement, emitFlags) - return tx.factory.NewSyntaxList(append(statements, enumStatement)) + enumFunc := tx.Factory().NewFunctionExpression(nil, nil, nil, nil, tx.Factory().NewNodeList([]*ast.Node{enumParam}), nil, enumBody) + enumCall := tx.Factory().NewCallExpression(tx.Factory().NewParenthesizedExpression(enumFunc), nil, nil, tx.Factory().NewNodeList([]*ast.Node{enumArg}), ast.NodeFlagsNone) + enumStatement := tx.Factory().NewExpressionStatement(enumCall) + tx.EmitContext().SetOriginal(enumStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(enumStatement, node.AsNode()) + tx.EmitContext().AddEmitFlags(enumStatement, emitFlags) + return tx.Factory().NewSyntaxList(append(statements, enumStatement)) } // Transforms the body of an enum declaration. @@ -358,11 +359,11 @@ func (tx *RuntimeSyntaxTransformer) transformEnumBody(node *ast.EnumDeclaration) tx.currentEnum = node.AsNode() // visit the children of `node` in advance to capture any references to enum members - node = tx.visitor.VisitEachChild(node.AsNode()).AsEnumDeclaration() + node = tx.Visitor().VisitEachChild(node.AsNode()).AsEnumDeclaration() statements := []*ast.Statement{} if len(node.Members.Nodes) > 0 { - tx.emitContext.StartVariableEnvironment() + tx.EmitContext().StartVariableEnvironment() var autoValue jsnum.Number var autoVar *ast.IdentifierNode @@ -380,14 +381,14 @@ func (tx *RuntimeSyntaxTransformer) transformEnumBody(node *ast.EnumDeclaration) autoValue++ } - statements = tx.emitContext.EndAndMergeVariableEnvironment(statements) + statements = tx.EmitContext().EndAndMergeVariableEnvironment(statements) } - statementList := tx.factory.NewNodeList(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = node.Members.Loc tx.currentEnum = savedCurrentEnum - return tx.factory.NewBlock(statementList, true /*multiline*/) + return tx.Factory().NewBlock(statementList, true /*multiline*/) } // Transforms an enum member into a statement. It is expected that `enum` has already been visited. @@ -426,7 +427,7 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( // emit. // E[E["A"] = ++auto] = "A"; // ^^^^^^ - expression = tx.factory.NewPrefixUnaryExpression(ast.KindPlusPlusToken, *autoVar) + expression = tx.Factory().NewPrefixUnaryExpression(ast.KindPlusPlusToken, *autoVar) useExplicitReverseMapping = true } else { // If the preceding auto value is a finite number, we can emit a numeric literal for the member initializer: @@ -435,14 +436,14 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( // If not, we cannot emit a valid numeric literal for the member initializer and emit `void 0` instead: // E["A"] = void 0; // ^^^^^^ - expression = constantExpression(*autoValue, tx.factory) + expression = constantExpression(*autoValue, tx.Factory()) if expression != nil { useExplicitReverseMapping = true if len(memberName) > 0 { tx.cacheEnumMemberValue(enum.AsNode(), memberName, evaluator.NewResult(*autoValue, false, false, false)) } } else { - expression = tx.factory.NewVoidZeroExpression() + expression = tx.Factory().NewVoidZeroExpression() } } } else { @@ -459,12 +460,12 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( case jsnum.Number: hasNumericInitializer = true *autoValue = value - expression = core.Coalesce(constantExpression(value, tx.factory), expression) // TODO: preserve original expression after Strada migration + expression = core.Coalesce(constantExpression(value, tx.Factory()), expression) // TODO: preserve original expression after Strada migration tx.cacheEnumMemberValue(enum.AsNode(), memberName, result) case string: hasStringInitializer = true *autoValue = jsnum.NaN() - expression = core.Coalesce(constantExpression(value, tx.factory), expression) // TODO: preserve original expression after Strada migration + expression = core.Coalesce(constantExpression(value, tx.Factory()), expression) // TODO: preserve original expression after Strada migration tx.cacheEnumMemberValue(enum.AsNode(), memberName, result) default: *autoValue = jsnum.NaN() @@ -477,17 +478,17 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( // E[E["A"] = auto = x] = "A"; // ^^^^^^^^ if *autoVar == nil { - *autoVar = tx.factory.NewUniqueNameEx("auto", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) - tx.emitContext.AddVariableDeclaration(*autoVar) + *autoVar = tx.Factory().NewUniqueNameEx("auto", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) + tx.EmitContext().AddVariableDeclaration(*autoVar) } - expression = tx.factory.NewAssignmentExpression(*autoVar, expression) + expression = tx.Factory().NewAssignmentExpression(*autoVar, expression) } } // Define the enum member property: // E[E["A"] = ++auto] = "A"; // ^^^^^^^^--_____ - expression = tx.factory.NewAssignmentExpression( + expression = tx.Factory().NewAssignmentExpression( tx.getEnumQualifiedElement(enum, member), expression, ) @@ -497,8 +498,8 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( if useExplicitReverseMapping { // E[E["A"] = A = ++auto] = "A"; // ^^-------------------^^^^^^^ - expression = tx.factory.NewAssignmentExpression( - tx.factory.NewElementAccessExpression( + expression = tx.Factory().NewAssignmentExpression( + tx.Factory().NewElementAccessExpression( tx.getNamespaceContainerName(enum.AsNode()), nil, /*questionDotToken*/ expression, @@ -508,9 +509,9 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( ) } - memberStatement := tx.factory.NewExpressionStatement(expression) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, member.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(memberStatement, member.AsNode()) + memberStatement := tx.Factory().NewExpressionStatement(expression) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, member.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(memberStatement, member.AsNode()) statements = append(statements, memberStatement) // If this is not auto numbered and is not syntactically a string or numeric literal initializer, then we @@ -520,14 +521,14 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( // if (typeof E.A !== "string") E.A = "A"; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ifStatement := tx.factory.NewIfStatement( - tx.factory.NewStrictInequalityExpression( - tx.factory.NewTypeOfExpression(tx.getEnumQualifiedReference(enum, member)), - tx.factory.NewStringLiteral("string"), + ifStatement := tx.Factory().NewIfStatement( + tx.Factory().NewStrictInequalityExpression( + tx.Factory().NewTypeOfExpression(tx.getEnumQualifiedReference(enum, member)), + tx.Factory().NewStringLiteral("string"), ), - tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewElementAccessExpression( + tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewElementAccessExpression( tx.getNamespaceContainerName(enum.AsNode()), nil, /*questionDotToken*/ tx.getEnumQualifiedReference(enum, member), @@ -539,8 +540,8 @@ func (tx *RuntimeSyntaxTransformer) transformEnumMember( nil, ) - tx.emitContext.AddEmitFlags(ifStatement, printer.EFSingleLine) - tx.emitContext.AssignSourceMapRange(ifStatement, member.Initializer) + tx.EmitContext().AddEmitFlags(ifStatement, printer.EFSingleLine) + tx.EmitContext().AssignSourceMapRange(ifStatement, member.Initializer) statements = append(statements, ifStatement) } @@ -565,35 +566,35 @@ func (tx *RuntimeSyntaxTransformer) visitModuleDeclaration(node *ast.ModuleDecla // x || (x = {}) // exports.x || (exports.x = {}) - moduleArg := tx.factory.NewLogicalORExpression( + moduleArg := tx.Factory().NewLogicalORExpression( tx.getExportQualifiedReferenceToDeclaration(node.AsNode()), - tx.factory.NewAssignmentExpression( + tx.Factory().NewAssignmentExpression( tx.getExportQualifiedReferenceToDeclaration(node.AsNode()), - tx.factory.NewObjectLiteralExpression(tx.factory.NewNodeList([]*ast.Node{}), false), + tx.Factory().NewObjectLiteralExpression(tx.Factory().NewNodeList([]*ast.Node{}), false), ), ) if tx.isExportOfNamespace(node.AsNode()) { // `localName` is the expression used within this node's containing scope for any local references. - localName := tx.factory.GetLocalNameEx(node.AsNode(), printer.AssignedNameOptions{AllowSourceMaps: true}) + localName := tx.Factory().GetLocalNameEx(node.AsNode(), printer.AssignedNameOptions{AllowSourceMaps: true}) // x = (exports.x || (exports.x = {})) - moduleArg = tx.factory.NewAssignmentExpression(localName, moduleArg) + moduleArg = tx.Factory().NewAssignmentExpression(localName, moduleArg) } // (function (name) { ... })(name || (name = {})) - moduleParamName := tx.factory.NewGeneratedNameForNode(node.AsNode()) - tx.emitContext.SetSourceMapRange(moduleParamName, node.Name().Loc) + moduleParamName := tx.Factory().NewGeneratedNameForNode(node.AsNode()) + tx.EmitContext().SetSourceMapRange(moduleParamName, node.Name().Loc) - moduleParam := tx.factory.NewParameterDeclaration(nil, nil, moduleParamName, nil, nil, nil) + moduleParam := tx.Factory().NewParameterDeclaration(nil, nil, moduleParamName, nil, nil, nil) moduleBody := tx.transformModuleBody(node, tx.getNamespaceContainerName(node.AsNode())) - moduleFunc := tx.factory.NewFunctionExpression(nil, nil, nil, nil, tx.factory.NewNodeList([]*ast.Node{moduleParam}), nil, moduleBody) - moduleCall := tx.factory.NewCallExpression(tx.factory.NewParenthesizedExpression(moduleFunc), nil, nil, tx.factory.NewNodeList([]*ast.Node{moduleArg}), ast.NodeFlagsNone) - moduleStatement := tx.factory.NewExpressionStatement(moduleCall) - tx.emitContext.SetOriginal(moduleStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(moduleStatement, node.AsNode()) - tx.emitContext.AddEmitFlags(moduleStatement, emitFlags) - return tx.factory.NewSyntaxList(append(statements, moduleStatement)) + moduleFunc := tx.Factory().NewFunctionExpression(nil, nil, nil, nil, tx.Factory().NewNodeList([]*ast.Node{moduleParam}), nil, moduleBody) + moduleCall := tx.Factory().NewCallExpression(tx.Factory().NewParenthesizedExpression(moduleFunc), nil, nil, tx.Factory().NewNodeList([]*ast.Node{moduleArg}), ast.NodeFlagsNone) + moduleStatement := tx.Factory().NewExpressionStatement(moduleCall) + tx.EmitContext().SetOriginal(moduleStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(moduleStatement, node.AsNode()) + tx.EmitContext().AddEmitFlags(moduleStatement, emitFlags) + return tx.Factory().NewSyntaxList(append(statements, moduleStatement)) } func (tx *RuntimeSyntaxTransformer) transformModuleBody(node *ast.ModuleDeclaration, namespaceLocalName *ast.IdentifierNode) *ast.BlockNode { @@ -605,21 +606,21 @@ func (tx *RuntimeSyntaxTransformer) transformModuleBody(node *ast.ModuleDeclarat tx.currentScopeFirstDeclarationsOfName = nil var statements []*ast.Statement - tx.emitContext.StartVariableEnvironment() + tx.EmitContext().StartVariableEnvironment() var statementsLocation core.TextRange var blockLocation core.TextRange if node.Body != nil { if node.Body.Kind == ast.KindModuleBlock { // visit the children of `node` in advance to capture any references to namespace members - node = tx.visitor.VisitEachChild(node.AsNode()).AsModuleDeclaration() + node = tx.Visitor().VisitEachChild(node.AsNode()).AsModuleDeclaration() body := node.Body.AsModuleBlock() statements = body.Statements.Nodes statementsLocation = body.Statements.Loc blockLocation = body.Loc } else { // node.Body.Kind == ast.KindModuleDeclaration tx.currentScope = node.AsNode() - statements, _ = tx.visitor.VisitSlice([]*ast.Node{node.Body}) + statements, _ = tx.Visitor().VisitSlice([]*ast.Node{node.Body}) moduleBlock := getInnermostModuleDeclarationFromDottedModule(node).Body.AsModuleBlock() statementsLocation = moduleBlock.Statements.Loc.WithPos(-1) } @@ -629,10 +630,10 @@ func (tx *RuntimeSyntaxTransformer) transformModuleBody(node *ast.ModuleDeclarat tx.currentScope = savedCurrentScope tx.currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName - statements = tx.emitContext.EndAndMergeVariableEnvironment(statements) - statementList := tx.factory.NewNodeList(statements) + statements = tx.EmitContext().EndAndMergeVariableEnvironment(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = statementsLocation - block := tx.factory.NewBlock(statementList, true /*multiline*/) + block := tx.Factory().NewBlock(statementList, true /*multiline*/) block.Loc = blockLocation // namespace hello.hi.world { @@ -657,28 +658,28 @@ func (tx *RuntimeSyntaxTransformer) transformModuleBody(node *ast.ModuleDeclarat // // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. if node.Body == nil || node.Body.Kind != ast.KindModuleBlock { - tx.emitContext.AddEmitFlags(block, printer.EFNoComments) + tx.EmitContext().AddEmitFlags(block, printer.EFNoComments) } return block } func (tx *RuntimeSyntaxTransformer) visitImportEqualsDeclaration(node *ast.ImportEqualsDeclaration) *ast.Node { if node.ModuleReference.Kind == ast.KindExternalModuleReference { - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } - moduleReference := convertEntityNameToExpression(tx.emitContext, node.ModuleReference) - tx.emitContext.SetEmitFlags(moduleReference, printer.EFNoComments|printer.EFNoNestedSourceMaps) + moduleReference := convertEntityNameToExpression(tx.EmitContext(), node.ModuleReference) + tx.EmitContext().SetEmitFlags(moduleReference, printer.EFNoComments|printer.EFNoNestedSourceMaps) if !tx.isExportOfNamespace(node.AsNode()) { // export var ${name} = ${moduleReference}; // var ${name} = ${moduleReference}; - varDecl := tx.factory.NewVariableDeclaration(node.Name(), nil /*exclamationToken*/, nil /*type*/, moduleReference) - tx.emitContext.SetOriginal(varDecl, node.AsNode()) - varList := tx.factory.NewVariableDeclarationList(ast.NodeFlagsNone, tx.factory.NewNodeList([]*ast.Node{varDecl})) - varModifiers := extractModifiers(tx.emitContext, node.Modifiers(), ast.ModifierFlagsExport) - varStatement := tx.factory.NewVariableStatement(varModifiers, varList) - tx.emitContext.SetOriginal(varStatement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) + varDecl := tx.Factory().NewVariableDeclaration(node.Name(), nil /*exclamationToken*/, nil /*type*/, moduleReference) + tx.EmitContext().SetOriginal(varDecl, node.AsNode()) + varList := tx.Factory().NewVariableDeclarationList(ast.NodeFlagsNone, tx.Factory().NewNodeList([]*ast.Node{varDecl})) + varModifiers := transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ast.ModifierFlagsExport) + varStatement := tx.Factory().NewVariableStatement(varModifiers, varList) + tx.EmitContext().SetOriginal(varStatement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(varStatement, node.AsNode()) return varStatement } else { // exports.${name} = ${moduleReference}; @@ -690,7 +691,7 @@ func (tx *RuntimeSyntaxTransformer) visitVariableStatement(node *ast.VariableSta if tx.isExportOfNamespace(node.AsNode()) { expressions := []*ast.Expression{} for _, declaration := range node.DeclarationList.AsVariableDeclarationList().Declarations.Nodes { - expression := convertVariableDeclarationToAssignmentExpression(tx.emitContext, declaration.AsVariableDeclaration()) + expression := transformers.ConvertVariableDeclarationToAssignmentExpression(tx.EmitContext(), declaration.AsVariableDeclaration()) if expression != nil { expressions = append(expressions, expression) } @@ -698,40 +699,40 @@ func (tx *RuntimeSyntaxTransformer) visitVariableStatement(node *ast.VariableSta if len(expressions) == 0 { return nil } - expression := tx.factory.InlineExpressions(expressions) - statement := tx.factory.NewExpressionStatement(expression) - tx.emitContext.SetOriginal(statement, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(statement, node.AsNode()) + expression := tx.Factory().InlineExpressions(expressions) + statement := tx.Factory().NewExpressionStatement(expression) + tx.EmitContext().SetOriginal(statement, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(statement, node.AsNode()) // re-visit as the new node savedCurrent := tx.currentNode tx.currentNode = statement - statement = tx.visitor.VisitEachChild(statement) + statement = tx.Visitor().VisitEachChild(statement) tx.currentNode = savedCurrent return statement } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } func (tx *RuntimeSyntaxTransformer) visitFunctionDeclaration(node *ast.FunctionDeclaration) *ast.Node { if tx.isExportOfNamespace(node.AsNode()) { - updated := tx.factory.UpdateFunctionDeclaration( + updated := tx.Factory().UpdateFunctionDeclaration( node, - tx.visitor.VisitModifiers(extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault)), + tx.Visitor().VisitModifiers(transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault)), node.AsteriskToken, - tx.visitor.VisitNode(node.Name()), + tx.Visitor().VisitNode(node.Name()), nil, /*typeParameters*/ - tx.visitor.VisitNodes(node.Parameters), + tx.Visitor().VisitNodes(node.Parameters), nil, /*returnType*/ - tx.visitor.VisitNode(node.Body), + tx.Visitor().VisitNode(node.Body), ) export := tx.createExportStatementForDeclaration(node.AsNode()) if export != nil { - return tx.factory.NewSyntaxList([]*ast.Node{updated, export}) + return tx.Factory().NewSyntaxList([]*ast.Node{updated, export}) } return updated } - return tx.visitor.VisitEachChild(node.AsNode()) + return tx.Visitor().VisitEachChild(node.AsNode()) } func (tx *RuntimeSyntaxTransformer) getParameterProperties(constructor *ast.Node) []*ast.ParameterDeclaration { @@ -750,98 +751,98 @@ func (tx *RuntimeSyntaxTransformer) visitClassDeclaration(node *ast.ClassDeclara exported := tx.isExportOfNamespace(node.AsNode()) var modifiers *ast.ModifierList if exported { - modifiers = tx.visitor.VisitModifiers(extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault)) + modifiers = tx.Visitor().VisitModifiers(transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault)) } else { - modifiers = tx.visitor.VisitModifiers(node.Modifiers()) + modifiers = tx.Visitor().VisitModifiers(node.Modifiers()) } - name := tx.visitor.VisitNode(node.Name()) - heritageClauses := tx.visitor.VisitNodes(node.HeritageClauses) - members := tx.visitor.VisitNodes(node.Members) + name := tx.Visitor().VisitNode(node.Name()) + heritageClauses := tx.Visitor().VisitNodes(node.HeritageClauses) + members := tx.Visitor().VisitNodes(node.Members) parameterProperties := tx.getParameterProperties(core.Find(node.Members.Nodes, ast.IsConstructorDeclaration)) if len(parameterProperties) > 0 { var newMembers []*ast.ClassElement for _, parameter := range parameterProperties { if ast.IsIdentifier(parameter.Name()) { - parameterProperty := tx.factory.NewPropertyDeclaration( + parameterProperty := tx.Factory().NewPropertyDeclaration( nil, /*modifiers*/ - parameter.Name().Clone(tx.factory), + parameter.Name().Clone(tx.Factory()), nil, /*questionOrExclamationToken*/ nil, /*type*/ nil, /*initializer*/ ) - tx.emitContext.SetOriginal(parameterProperty, parameter.AsNode()) + tx.EmitContext().SetOriginal(parameterProperty, parameter.AsNode()) newMembers = append(newMembers, parameterProperty) } } if len(newMembers) > 0 { newMembers = append(newMembers, members.Nodes...) - members = tx.factory.NewNodeList(newMembers) + members = tx.Factory().NewNodeList(newMembers) members.Loc = node.Members.Loc } } - updated := tx.factory.UpdateClassDeclaration(node, modifiers, name, nil /*typeParameters*/, heritageClauses, members) + updated := tx.Factory().UpdateClassDeclaration(node, modifiers, name, nil /*typeParameters*/, heritageClauses, members) if exported { export := tx.createExportStatementForDeclaration(node.AsNode()) if export != nil { - return tx.factory.NewSyntaxList([]*ast.Node{updated, export}) + return tx.Factory().NewSyntaxList([]*ast.Node{updated, export}) } } return updated } func (tx *RuntimeSyntaxTransformer) visitClassExpression(node *ast.ClassExpression) *ast.Node { - modifiers := tx.visitor.VisitModifiers(extractModifiers(tx.emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault)) - name := tx.visitor.VisitNode(node.Name()) - heritageClauses := tx.visitor.VisitNodes(node.HeritageClauses) - members := tx.visitor.VisitNodes(node.Members) + modifiers := tx.Visitor().VisitModifiers(transformers.ExtractModifiers(tx.EmitContext(), node.Modifiers(), ^ast.ModifierFlagsExportDefault)) + name := tx.Visitor().VisitNode(node.Name()) + heritageClauses := tx.Visitor().VisitNodes(node.HeritageClauses) + members := tx.Visitor().VisitNodes(node.Members) parameterProperties := tx.getParameterProperties(core.Find(node.Members.Nodes, ast.IsConstructorDeclaration)) if len(parameterProperties) > 0 { var newMembers []*ast.ClassElement for _, parameter := range parameterProperties { if ast.IsIdentifier(parameter.Name()) { - parameterProperty := tx.factory.NewPropertyDeclaration( + parameterProperty := tx.Factory().NewPropertyDeclaration( nil, /*modifiers*/ - parameter.Name().Clone(tx.factory), + parameter.Name().Clone(tx.Factory()), nil, /*questionOrExclamationToken*/ nil, /*type*/ nil, /*initializer*/ ) - tx.emitContext.SetOriginal(parameterProperty, parameter.AsNode()) + tx.EmitContext().SetOriginal(parameterProperty, parameter.AsNode()) newMembers = append(newMembers, parameterProperty) } } if len(newMembers) > 0 { newMembers = append(newMembers, members.Nodes...) - members = tx.factory.NewNodeList(newMembers) + members = tx.Factory().NewNodeList(newMembers) members.Loc = node.Members.Loc } } - return tx.factory.UpdateClassExpression(node, modifiers, name, nil /*typeParameters*/, heritageClauses, members) + return tx.Factory().UpdateClassExpression(node, modifiers, name, nil /*typeParameters*/, heritageClauses, members) } func (tx *RuntimeSyntaxTransformer) visitConstructorDeclaration(node *ast.ConstructorDeclaration) *ast.Node { - modifiers := tx.visitor.VisitModifiers(node.Modifiers()) - parameters := tx.emitContext.VisitParameters(node.ParameterList(), tx.visitor) + modifiers := tx.Visitor().VisitModifiers(node.Modifiers()) + parameters := tx.EmitContext().VisitParameters(node.ParameterList(), tx.Visitor()) body := tx.visitConstructorBody(node.Body.AsBlock(), node.AsNode()) - return tx.factory.UpdateConstructorDeclaration(node, modifiers, nil /*typeParameters*/, parameters, nil /*returnType*/, body) + return tx.Factory().UpdateConstructorDeclaration(node, modifiers, nil /*typeParameters*/, parameters, nil /*returnType*/, body) } func (tx *RuntimeSyntaxTransformer) visitConstructorBody(body *ast.Block, constructor *ast.Node) *ast.Node { parameterProperties := tx.getParameterProperties(constructor) if len(parameterProperties) == 0 { - return tx.emitContext.VisitFunctionBody(body.AsNode(), tx.visitor) + return tx.EmitContext().VisitFunctionBody(body.AsNode(), tx.Visitor()) } grandparentOfBody := tx.pushNode(body.AsNode()) savedCurrentScope, savedCurrentScopeFirstDeclarationsOfName := tx.pushScope(body.AsNode()) - tx.emitContext.StartVariableEnvironment() - prologue, rest := tx.factory.SplitStandardPrologue(body.Statements.Nodes) + tx.EmitContext().StartVariableEnvironment() + prologue, rest := tx.Factory().SplitStandardPrologue(body.Statements.Nodes) statements := slices.Clone(prologue) // Transform parameters into property assignments. Transforms this: @@ -860,16 +861,16 @@ func (tx *RuntimeSyntaxTransformer) visitConstructorBody(body *ast.Block, constr var parameterPropertyAssignments []*ast.Statement for _, parameter := range parameterProperties { if ast.IsIdentifier(parameter.Name()) { - propertyName := parameter.Name().Clone(tx.factory) - tx.emitContext.AddEmitFlags(propertyName, printer.EFNoComments|printer.EFNoSourceMap) + propertyName := parameter.Name().Clone(tx.Factory()) + tx.EmitContext().AddEmitFlags(propertyName, printer.EFNoComments|printer.EFNoSourceMap) - localName := parameter.Name().Clone(tx.factory) - tx.emitContext.AddEmitFlags(localName, printer.EFNoComments) + localName := parameter.Name().Clone(tx.Factory()) + tx.EmitContext().AddEmitFlags(localName, printer.EFNoComments) - parameterProperty := tx.factory.NewExpressionStatement( - tx.factory.NewAssignmentExpression( - tx.factory.NewPropertyAccessExpression( - tx.factory.NewThisExpression(), + parameterProperty := tx.Factory().NewExpressionStatement( + tx.Factory().NewAssignmentExpression( + tx.Factory().NewPropertyAccessExpression( + tx.Factory().NewThisExpression(), nil, /*questionDotToken*/ propertyName, ast.NodeFlagsNone, @@ -877,8 +878,8 @@ func (tx *RuntimeSyntaxTransformer) visitConstructorBody(body *ast.Block, constr localName, ), ) - tx.emitContext.SetOriginal(parameterProperty, parameter.AsNode()) - tx.emitContext.AddEmitFlags(parameterProperty, printer.EFStartOnNewLine) + tx.EmitContext().SetOriginal(parameterProperty, parameter.AsNode()) + tx.EmitContext().AddEmitFlags(parameterProperty, printer.EFStartOnNewLine) parameterPropertyAssignments = append(parameterPropertyAssignments, parameterProperty) } } @@ -892,17 +893,17 @@ func (tx *RuntimeSyntaxTransformer) visitConstructorBody(body *ast.Block, constr statements = append(statements, tx.transformConstructorBodyWorker(rest, superPath, parameterPropertyAssignments)...) } else { statements = append(statements, parameterPropertyAssignments...) - statements = append(statements, core.FirstResult(tx.visitor.VisitSlice(rest))...) + statements = append(statements, core.FirstResult(tx.Visitor().VisitSlice(rest))...) } - statements = tx.emitContext.EndAndMergeVariableEnvironment(statements) - statementList := tx.factory.NewNodeList(statements) + statements = tx.EmitContext().EndAndMergeVariableEnvironment(statements) + statementList := tx.Factory().NewNodeList(statements) statementList.Loc = body.Statements.Loc tx.popScope(savedCurrentScope, savedCurrentScopeFirstDeclarationsOfName) tx.popNode(grandparentOfBody) - updated := tx.factory.NewBlock(statementList /*multiline*/, true) - tx.emitContext.SetOriginal(updated, body.AsNode()) + updated := tx.Factory().NewBlock(statementList /*multiline*/, true) + tx.EmitContext().SetOriginal(updated, body.AsNode()) updated.Loc = body.Loc return updated } @@ -940,7 +941,7 @@ func (tx *RuntimeSyntaxTransformer) transformConstructorBodyWorker(statementsIn superStatement := statementsIn[superStatementIndex] // visit up to the statement containing `super` - statementsOut = append(statementsOut, core.FirstResult(tx.visitor.VisitSlice(statementsIn[:superStatementIndex]))...) + statementsOut = append(statementsOut, core.FirstResult(tx.Visitor().VisitSlice(statementsIn[:superStatementIndex]))...) // if the statement containing `super` is a `try` statement, transform the body of the `try` block if ast.IsTryStatement(superStatement) { @@ -963,27 +964,27 @@ func (tx *RuntimeSyntaxTransformer) transformConstructorBodyWorker(statementsIn tx.popScope(savedCurrentScope, savedCurrentScopeFirstDeclarationsOfName) tx.popNode(grandparentOfTryBlock) - tryBlockStatementList := tx.factory.NewNodeList(tryBlockStatements) + tryBlockStatementList := tx.Factory().NewNodeList(tryBlockStatements) tryBlockStatementList.Loc = tryBlock.Statements.Loc - statementsOut = append(statementsOut, tx.factory.UpdateTryStatement( + statementsOut = append(statementsOut, tx.Factory().UpdateTryStatement( tryStatement, - tx.factory.UpdateBlock(tryBlock, tryBlockStatementList), - tx.visitor.VisitNode(tryStatement.CatchClause), - tx.visitor.VisitNode(tryStatement.FinallyBlock), + tx.Factory().UpdateBlock(tryBlock, tryBlockStatementList), + tx.Visitor().VisitNode(tryStatement.CatchClause), + tx.Visitor().VisitNode(tryStatement.FinallyBlock), )) // restore hierarchy as we ascend to the parent of the `try` statement tx.popNode(grandparentOfTryStatement) } else { // visit the statement containing `super` - statementsOut = append(statementsOut, core.FirstResult(tx.visitor.VisitSlice(statementsIn[superStatementIndex:superStatementIndex+1]))...) + statementsOut = append(statementsOut, core.FirstResult(tx.Visitor().VisitSlice(statementsIn[superStatementIndex:superStatementIndex+1]))...) // insert the initializer statements statementsOut = append(statementsOut, initializerStatements...) } // visit the statements after `super` - statementsOut = append(statementsOut, core.FirstResult(tx.visitor.VisitSlice(statementsIn[superStatementIndex+1:]))...) + statementsOut = append(statementsOut, core.FirstResult(tx.Visitor().VisitSlice(statementsIn[superStatementIndex+1:]))...) return statementsOut } @@ -995,43 +996,43 @@ func (tx *RuntimeSyntaxTransformer) visitShorthandPropertyAssignment(node *ast.S if node.ObjectAssignmentInitializer != nil { equalsToken := node.EqualsToken if equalsToken == nil { - equalsToken = tx.factory.NewToken(ast.KindEqualsToken) + equalsToken = tx.Factory().NewToken(ast.KindEqualsToken) } - expression = tx.factory.NewBinaryExpression( + expression = tx.Factory().NewBinaryExpression( nil, /*modifiers*/ expression, nil, /*typeNode*/ equalsToken, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } - updated := tx.factory.NewPropertyAssignment(nil /*modifiers*/, node.Name(), nil /*postfixToken*/, nil /*typeNode*/, expression) + updated := tx.Factory().NewPropertyAssignment(nil /*modifiers*/, node.Name(), nil /*postfixToken*/, nil /*typeNode*/, expression) updated.Loc = node.Loc - tx.emitContext.SetOriginal(updated, node.AsNode()) - tx.emitContext.AssignCommentAndSourceMapRanges(updated, node.AsNode()) + tx.EmitContext().SetOriginal(updated, node.AsNode()) + tx.EmitContext().AssignCommentAndSourceMapRanges(updated, node.AsNode()) return updated } - return tx.factory.UpdateShorthandPropertyAssignment(node, + return tx.Factory().UpdateShorthandPropertyAssignment(node, nil, /*modifiers*/ exportedOrImportedName, nil, /*postfixToken*/ nil, /*typeNode*/ node.EqualsToken, - tx.visitor.VisitNode(node.ObjectAssignmentInitializer), + tx.Visitor().VisitNode(node.ObjectAssignmentInitializer), ) } func (tx *RuntimeSyntaxTransformer) visitIdentifier(node *ast.IdentifierNode) *ast.Node { - if isIdentifierReference(node, tx.parentNode) { + if transformers.IsIdentifierReference(node, tx.parentNode) { return tx.visitExpressionIdentifier(node) } return node } func (tx *RuntimeSyntaxTransformer) visitExpressionIdentifier(node *ast.IdentifierNode) *ast.Node { - if (tx.currentEnum != nil || tx.currentNamespace != nil) && !isGeneratedIdentifier(tx.emitContext, node) && !isLocalName(tx.emitContext, node) { - location := tx.emitContext.MostOriginal(node.AsNode()) + if (tx.currentEnum != nil || tx.currentNamespace != nil) && !transformers.IsGeneratedIdentifier(tx.EmitContext(), node) && !transformers.IsLocalName(tx.EmitContext(), node) { + location := tx.EmitContext().MostOriginal(node.AsNode()) if tx.resolver == nil { tx.resolver = binder.NewReferenceResolver(tx.compilerOptions, binder.ReferenceResolverHooks{}) } @@ -1039,11 +1040,11 @@ func (tx *RuntimeSyntaxTransformer) visitExpressionIdentifier(node *ast.Identifi if container != nil && (ast.IsEnumDeclaration(container) || ast.IsModuleDeclaration(container)) && container.Contains(location) { containerName := tx.getNamespaceContainerName(container) - memberName := node.Clone(tx.factory) - tx.emitContext.SetEmitFlags(memberName, printer.EFNoComments|printer.EFNoSourceMap) + memberName := node.Clone(tx.Factory()) + tx.EmitContext().SetEmitFlags(memberName, printer.EFNoComments|printer.EFNoSourceMap) - expression := tx.factory.GetNamespaceMemberName(containerName, memberName, printer.NameOptions{AllowSourceMaps: true}) - tx.emitContext.AssignCommentAndSourceMapRanges(expression, node.AsNode()) + expression := tx.Factory().GetNamespaceMemberName(containerName, memberName, printer.NameOptions{AllowSourceMaps: true}) + tx.EmitContext().AssignCommentAndSourceMapRanges(expression, node.AsNode()) return expression } } @@ -1056,7 +1057,7 @@ func (tx *RuntimeSyntaxTransformer) createExportStatementForDeclaration(node *as return nil } - localName := tx.factory.GetLocalName(node) + localName := tx.Factory().GetLocalName(node) exportAssignmentSourceMapRange := node.Loc if node.Name() != nil { exportAssignmentSourceMapRange = exportAssignmentSourceMapRange.WithPos(name.Pos()) @@ -1067,16 +1068,16 @@ func (tx *RuntimeSyntaxTransformer) createExportStatementForDeclaration(node *as func (tx *RuntimeSyntaxTransformer) createExportAssignment(name *ast.IdentifierNode, expression *ast.Expression, exportAssignmentSourceMapRange core.TextRange, original *ast.Node) *ast.Expression { exportName := tx.getNamespaceQualifiedProperty(tx.getNamespaceContainerName(tx.currentNamespace), name) - exportAssignment := tx.factory.NewAssignmentExpression(exportName, expression) - tx.emitContext.SetOriginal(exportAssignment, original) - tx.emitContext.SetSourceMapRange(exportAssignment, exportAssignmentSourceMapRange) + exportAssignment := tx.Factory().NewAssignmentExpression(exportName, expression) + tx.EmitContext().SetOriginal(exportAssignment, original) + tx.EmitContext().SetSourceMapRange(exportAssignment, exportAssignmentSourceMapRange) return exportAssignment } func (tx *RuntimeSyntaxTransformer) createExportStatement(name *ast.IdentifierNode, expression *ast.Expression, exportAssignmentSourceMapRange core.TextRange, exportStatementSourceMapRange core.TextRange, original *ast.Node) *ast.Statement { - exportStatement := tx.factory.NewExpressionStatement(tx.createExportAssignment(name, expression, exportAssignmentSourceMapRange, original)) - tx.emitContext.SetOriginal(exportStatement, original) - tx.emitContext.SetSourceMapRange(exportStatement, exportStatementSourceMapRange) + exportStatement := tx.Factory().NewExpressionStatement(tx.createExportAssignment(name, expression, exportAssignmentSourceMapRange, original)) + tx.EmitContext().SetOriginal(exportStatement, original) + tx.EmitContext().SetSourceMapRange(exportStatement, exportStatementSourceMapRange) return exportStatement } @@ -1093,9 +1094,9 @@ func (tx *RuntimeSyntaxTransformer) cacheEnumMemberValue(enum *ast.EnumDeclarati } func (tx *RuntimeSyntaxTransformer) isReferenceToEnum(reference *ast.IdentifierNode, enum *ast.EnumDeclarationNode) bool { - if isGeneratedIdentifier(tx.emitContext, reference) { - originalEnum := tx.emitContext.MostOriginal(enum) - return tx.emitContext.GetNodeForGeneratedName(reference) == originalEnum + if transformers.IsGeneratedIdentifier(tx.EmitContext(), reference) { + originalEnum := tx.EmitContext().MostOriginal(enum) + return tx.EmitContext().GetNodeForGeneratedName(reference) == originalEnum } return reference.Text() == enum.Name().Text() } diff --git a/internal/transformers/runtimesyntax_test.go b/internal/transformers/tstransforms/runtimesyntax_test.go similarity index 95% rename from internal/transformers/runtimesyntax_test.go rename to internal/transformers/tstransforms/runtimesyntax_test.go index 617d3bbb21..dda47e6a92 100644 --- a/internal/transformers/runtimesyntax_test.go +++ b/internal/transformers/tstransforms/runtimesyntax_test.go @@ -1,4 +1,4 @@ -package transformers +package tstransforms_test import ( "testing" @@ -8,6 +8,7 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" ) func TestEnumTransformer(t *testing.T) { @@ -236,7 +237,7 @@ var E; binder.BindSourceFile(file) emitContext := printer.NewEmitContext() resolver := binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{}) - emittestutil.CheckEmit(t, emitContext, NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file), rec.output) + emittestutil.CheckEmit(t, emitContext, tstransforms.NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file), rec.output) }) } } @@ -414,7 +415,7 @@ func TestNamespaceTransformer(t *testing.T) { binder.BindSourceFile(file) emitContext := printer.NewEmitContext() resolver := binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{}) - emittestutil.CheckEmit(t, emitContext, NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file), rec.output) + emittestutil.CheckEmit(t, emitContext, tstransforms.NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file), rec.output) }) } } @@ -450,8 +451,8 @@ func TestParameterPropertyTransformer(t *testing.T) { binder.BindSourceFile(file) emitContext := printer.NewEmitContext() resolver := binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{}) - file = NewTypeEraserTransformer(emitContext, options).TransformSourceFile(file) - file = NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file) + file = tstransforms.NewTypeEraserTransformer(emitContext, options).TransformSourceFile(file) + file = tstransforms.NewRuntimeSyntaxTransformer(emitContext, options, resolver).TransformSourceFile(file) emittestutil.CheckEmit(t, emitContext, file, rec.output) }) } diff --git a/internal/transformers/typeeraser.go b/internal/transformers/tstransforms/typeeraser.go similarity index 62% rename from internal/transformers/typeeraser.go rename to internal/transformers/tstransforms/typeeraser.go index aa39d06db7..1d0d96c83e 100644 --- a/internal/transformers/typeeraser.go +++ b/internal/transformers/tstransforms/typeeraser.go @@ -1,19 +1,20 @@ -package transformers +package tstransforms import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/transformers" ) type TypeEraserTransformer struct { - Transformer + transformers.Transformer compilerOptions *core.CompilerOptions parentNode *ast.Node currentNode *ast.Node } -func NewTypeEraserTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions) *Transformer { +func NewTypeEraserTransformer(emitContext *printer.EmitContext, compilerOptions *core.CompilerOptions) *transformers.Transformer { tx := &TypeEraserTransformer{compilerOptions: compilerOptions} return tx.NewTransformer(tx.visit, emitContext) } @@ -33,8 +34,8 @@ func (tx *TypeEraserTransformer) popNode(grandparentNode *ast.Node) { } func (tx *TypeEraserTransformer) elide(node *ast.Statement) *ast.Statement { - statement := tx.factory.NewNotEmittedStatement() - tx.emitContext.SetOriginal(statement, node) + statement := tx.Factory().NewNotEmittedStatement() + tx.EmitContext().SetOriginal(statement, node) statement.Loc = node.Loc return statement } @@ -115,11 +116,11 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript module declarations are elided if they are not instantiated or have no body return tx.elide(node) } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindExpressionWithTypeArguments: n := node.AsExpressionWithTypeArguments() - return tx.factory.UpdateExpressionWithTypeArguments(n, tx.visitor.VisitNode(n.Expression), nil) + return tx.Factory().UpdateExpressionWithTypeArguments(n, tx.Visitor().VisitNode(n.Expression), nil) case ast.KindPropertyDeclaration: if ast.HasSyntacticModifier(node, ast.ModifierFlagsAmbient) { @@ -127,7 +128,7 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { return nil } n := node.AsPropertyDeclaration() - return tx.factory.UpdatePropertyDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), tx.visitor.VisitNode(n.Name()), nil, nil, tx.visitor.VisitNode(n.Initializer)) + return tx.Factory().UpdatePropertyDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), tx.Visitor().VisitNode(n.Name()), nil, nil, tx.Visitor().VisitNode(n.Initializer)) case ast.KindConstructor: n := node.AsConstructorDeclaration() @@ -135,7 +136,7 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript overloads are elided return nil } - return tx.factory.UpdateConstructorDeclaration(n, nil, nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateConstructorDeclaration(n, nil, nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindMethodDeclaration: n := node.AsMethodDeclaration() @@ -143,7 +144,7 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript overloads are elided return nil } - return tx.factory.UpdateMethodDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.visitor.VisitNode(n.Name()), nil, nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateMethodDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.Visitor().VisitNode(n.Name()), nil, nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindGetAccessor: n := node.AsGetAccessorDeclaration() @@ -151,7 +152,7 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript overloads are elided return nil } - return tx.factory.UpdateGetAccessorDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateGetAccessorDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindSetAccessor: n := node.AsSetAccessorDeclaration() @@ -159,11 +160,11 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript overloads are elided return nil } - return tx.factory.UpdateSetAccessorDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateSetAccessorDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindVariableDeclaration: n := node.AsVariableDeclaration() - return tx.factory.UpdateVariableDeclaration(n, tx.visitor.VisitNode(n.Name()), nil, nil, tx.visitor.VisitNode(n.Initializer)) + return tx.Factory().UpdateVariableDeclaration(n, tx.Visitor().VisitNode(n.Name()), nil, nil, tx.Visitor().VisitNode(n.Initializer)) case ast.KindHeritageClause: n := node.AsHeritageClause() @@ -171,15 +172,15 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript `implements` clauses are elided return nil } - return tx.factory.UpdateHeritageClause(n, tx.visitor.VisitNodes(n.Types)) + return tx.Factory().UpdateHeritageClause(n, tx.Visitor().VisitNodes(n.Types)) case ast.KindClassDeclaration: n := node.AsClassDeclaration() - return tx.factory.UpdateClassDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.HeritageClauses), tx.visitor.VisitNodes(n.Members)) + return tx.Factory().UpdateClassDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.HeritageClauses), tx.Visitor().VisitNodes(n.Members)) case ast.KindClassExpression: n := node.AsClassExpression() - return tx.factory.UpdateClassExpression(n, tx.visitor.VisitModifiers(n.Modifiers()), tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.HeritageClauses), tx.visitor.VisitNodes(n.Members)) + return tx.Factory().UpdateClassExpression(n, tx.Visitor().VisitModifiers(n.Modifiers()), tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.HeritageClauses), tx.Visitor().VisitNodes(n.Members)) case ast.KindFunctionDeclaration: n := node.AsFunctionDeclaration() @@ -187,15 +188,15 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // TypeScript overloads are elided return tx.elide(node) } - return tx.factory.UpdateFunctionDeclaration(n, tx.visitor.VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateFunctionDeclaration(n, tx.Visitor().VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindFunctionExpression: n := node.AsFunctionExpression() - return tx.factory.UpdateFunctionExpression(n, tx.visitor.VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.visitor.VisitNode(n.Name()), nil, tx.visitor.VisitNodes(n.Parameters), nil, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateFunctionExpression(n, tx.Visitor().VisitModifiers(n.Modifiers()), n.AsteriskToken, tx.Visitor().VisitNode(n.Name()), nil, tx.Visitor().VisitNodes(n.Parameters), nil, tx.Visitor().VisitNode(n.Body)) case ast.KindArrowFunction: n := node.AsArrowFunction() - return tx.factory.UpdateArrowFunction(n, tx.visitor.VisitModifiers(n.Modifiers()), nil, tx.visitor.VisitNodes(n.Parameters), nil, n.EqualsGreaterThanToken, tx.visitor.VisitNode(n.Body)) + return tx.Factory().UpdateArrowFunction(n, tx.Visitor().VisitModifiers(n.Modifiers()), nil, tx.Visitor().VisitNodes(n.Parameters), nil, n.EqualsGreaterThanToken, tx.Visitor().VisitNode(n.Body)) case ast.KindParameter: if ast.IsThisParameter(node) { @@ -206,25 +207,25 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // preserve parameter property modifiers to be handled by the runtime transformer var modifiers *ast.ModifierList if ast.IsParameterPropertyDeclaration(node, tx.parentNode) { - modifiers = extractModifiers(tx.emitContext, n.Modifiers(), ast.ModifierFlagsParameterPropertyModifier) + modifiers = transformers.ExtractModifiers(tx.EmitContext(), n.Modifiers(), ast.ModifierFlagsParameterPropertyModifier) } - return tx.factory.UpdateParameterDeclaration(n, modifiers, n.DotDotDotToken, tx.visitor.VisitNode(n.Name()), nil, nil, tx.visitor.VisitNode(n.Initializer)) + return tx.Factory().UpdateParameterDeclaration(n, modifiers, n.DotDotDotToken, tx.Visitor().VisitNode(n.Name()), nil, nil, tx.Visitor().VisitNode(n.Initializer)) case ast.KindCallExpression: n := node.AsCallExpression() - return tx.factory.UpdateCallExpression(n, tx.visitor.VisitNode(n.Expression), n.QuestionDotToken, nil, tx.visitor.VisitNodes(n.Arguments)) + return tx.Factory().UpdateCallExpression(n, tx.Visitor().VisitNode(n.Expression), n.QuestionDotToken, nil, tx.Visitor().VisitNodes(n.Arguments)) case ast.KindNewExpression: n := node.AsNewExpression() - return tx.factory.UpdateNewExpression(n, tx.visitor.VisitNode(n.Expression), nil, tx.visitor.VisitNodes(n.Arguments)) + return tx.Factory().UpdateNewExpression(n, tx.Visitor().VisitNode(n.Expression), nil, tx.Visitor().VisitNodes(n.Arguments)) case ast.KindTaggedTemplateExpression: n := node.AsTaggedTemplateExpression() - return tx.factory.UpdateTaggedTemplateExpression(n, tx.visitor.VisitNode(n.Tag), n.QuestionDotToken, nil, tx.visitor.VisitNode(n.Template)) + return tx.Factory().UpdateTaggedTemplateExpression(n, tx.Visitor().VisitNode(n.Tag), n.QuestionDotToken, nil, tx.Visitor().VisitNode(n.Template)) case ast.KindNonNullExpression, ast.KindTypeAssertionExpression, ast.KindAsExpression, ast.KindSatisfiesExpression: - partial := tx.factory.NewPartiallyEmittedExpression(tx.visitor.VisitNode(node.Expression())) - tx.emitContext.SetOriginal(partial, node) + partial := tx.Factory().NewPartiallyEmittedExpression(tx.Visitor().VisitNode(node.Expression())) + tx.EmitContext().SetOriginal(partial, node) partial.Loc = node.Loc return partial @@ -232,20 +233,20 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { n := node.AsParenthesizedExpression() expression := ast.SkipOuterExpressions(n.Expression, ^(ast.OEKAssertions | ast.OEKExpressionsWithTypeArguments)) if ast.IsAssertionExpression(expression) || ast.IsSatisfiesExpression(expression) { - partial := tx.factory.NewPartiallyEmittedExpression(tx.visitor.VisitNode(n.Expression)) - tx.emitContext.SetOriginal(partial, node) + partial := tx.Factory().NewPartiallyEmittedExpression(tx.Visitor().VisitNode(n.Expression)) + tx.EmitContext().SetOriginal(partial, node) partial.Loc = node.Loc return partial } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindJsxSelfClosingElement: n := node.AsJsxSelfClosingElement() - return tx.factory.UpdateJsxSelfClosingElement(n, tx.visitor.VisitNode(n.TagName), nil, tx.visitor.VisitNode(n.Attributes)) + return tx.Factory().UpdateJsxSelfClosingElement(n, tx.Visitor().VisitNode(n.TagName), nil, tx.Visitor().VisitNode(n.Attributes)) case ast.KindJsxOpeningElement: n := node.AsJsxOpeningElement() - return tx.factory.UpdateJsxOpeningElement(n, tx.visitor.VisitNode(n.TagName), nil, tx.visitor.VisitNode(n.Attributes)) + return tx.Factory().UpdateJsxOpeningElement(n, tx.Visitor().VisitNode(n.TagName), nil, tx.Visitor().VisitNode(n.Attributes)) case ast.KindImportEqualsDeclaration: n := node.AsImportEqualsDeclaration() @@ -253,7 +254,7 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // elide type-only imports return nil } - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) case ast.KindImportDeclaration: n := node.AsImportDeclaration() @@ -262,11 +263,11 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // import "foo"; return node } - importClause := tx.visitor.VisitNode(n.ImportClause) + importClause := tx.Visitor().VisitNode(n.ImportClause) if importClause == nil { return nil } - return tx.factory.UpdateImportDeclaration(n, n.Modifiers(), importClause, n.ModuleSpecifier, n.Attributes) + return tx.Factory().UpdateImportDeclaration(n, n.Modifiers(), importClause, n.ModuleSpecifier, n.Attributes) case ast.KindImportClause: n := node.AsImportClause() @@ -275,12 +276,12 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { return nil } name := n.Name() - namedBindings := tx.visitor.VisitNode(n.NamedBindings) + namedBindings := tx.Visitor().VisitNode(n.NamedBindings) if name == nil && namedBindings == nil { // all import bindings were elided return nil } - return tx.factory.UpdateImportClause(n, false /*isTypeOnly*/, name, namedBindings) + return tx.Factory().UpdateImportClause(n, false /*isTypeOnly*/, name, namedBindings) case ast.KindNamedImports: n := node.AsNamedImports() @@ -288,12 +289,12 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { // Do not elide a side-effect only import declaration. return node } - elements := tx.visitor.VisitNodes(n.Elements) + elements := tx.Visitor().VisitNodes(n.Elements) if !tx.compilerOptions.VerbatimModuleSyntax.IsTrue() && len(elements.Nodes) == 0 { // all import specifiers were elided return nil } - return tx.factory.UpdateNamedImports(n, elements) + return tx.Factory().UpdateNamedImports(n, elements) case ast.KindImportSpecifier: n := node.AsImportSpecifier() @@ -311,13 +312,13 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { } var exportClause *ast.Node if n.ExportClause != nil { - exportClause = tx.visitor.VisitNode(n.ExportClause) + exportClause = tx.Visitor().VisitNode(n.ExportClause) if exportClause == nil { // all export bindings were elided return nil } } - return tx.factory.UpdateExportDeclaration(n, nil /*modifiers*/, false /*isTypeOnly*/, exportClause, tx.visitor.VisitNode(n.ModuleSpecifier), tx.visitor.VisitNode(n.Attributes)) + return tx.Factory().UpdateExportDeclaration(n, nil /*modifiers*/, false /*isTypeOnly*/, exportClause, tx.Visitor().VisitNode(n.ModuleSpecifier), tx.Visitor().VisitNode(n.Attributes)) case ast.KindNamedExports: n := node.AsNamedExports() @@ -326,12 +327,12 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { return node } - elements := tx.visitor.VisitNodes(n.Elements) + elements := tx.Visitor().VisitNodes(n.Elements) if !tx.compilerOptions.VerbatimModuleSyntax.IsTrue() && len(elements.Nodes) == 0 { // all export specifiers were elided return nil } - return tx.factory.UpdateNamedExports(n, elements) + return tx.Factory().UpdateNamedExports(n, elements) case ast.KindExportSpecifier: n := node.AsExportSpecifier() @@ -342,6 +343,6 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { return node default: - return tx.visitor.VisitEachChild(node) + return tx.Visitor().VisitEachChild(node) } } diff --git a/internal/transformers/typeeraser_test.go b/internal/transformers/tstransforms/typeeraser_test.go similarity index 96% rename from internal/transformers/typeeraser_test.go rename to internal/transformers/tstransforms/typeeraser_test.go index f0ae9d03a4..e57fbc8022 100644 --- a/internal/transformers/typeeraser_test.go +++ b/internal/transformers/tstransforms/typeeraser_test.go @@ -1,4 +1,4 @@ -package transformers +package tstransforms_test import ( "testing" @@ -7,6 +7,7 @@ import ( "github.com/microsoft/typescript-go/internal/printer" "github.com/microsoft/typescript-go/internal/testutil/emittestutil" "github.com/microsoft/typescript-go/internal/testutil/parsetestutil" + "github.com/microsoft/typescript-go/internal/transformers/tstransforms" ) func TestTypeEraser(t *testing.T) { @@ -98,7 +99,7 @@ func TestTypeEraser(t *testing.T) { if rec.vms { compilerOptions.VerbatimModuleSyntax = core.TSTrue } - emittestutil.CheckEmit(t, nil, NewTypeEraserTransformer(printer.NewEmitContext(), compilerOptions).TransformSourceFile(file), rec.output) + emittestutil.CheckEmit(t, nil, tstransforms.NewTypeEraserTransformer(printer.NewEmitContext(), compilerOptions).TransformSourceFile(file), rec.output) }) } } diff --git a/internal/transformers/tstransforms/utilities.go b/internal/transformers/tstransforms/utilities.go new file mode 100644 index 0000000000..ead7be4bb8 --- /dev/null +++ b/internal/transformers/tstransforms/utilities.go @@ -0,0 +1,41 @@ +package tstransforms + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/jsnum" + "github.com/microsoft/typescript-go/internal/printer" +) + +func convertEntityNameToExpression(emitContext *printer.EmitContext, name *ast.EntityName) *ast.Expression { + if ast.IsQualifiedName(name) { + left := convertEntityNameToExpression(emitContext, name.AsQualifiedName().Left) + right := name.AsQualifiedName().Right + prop := emitContext.Factory.NewPropertyAccessExpression(left, nil /*questionDotToken*/, right, ast.NodeFlagsNone) + emitContext.SetOriginal(prop, name) + emitContext.AssignCommentAndSourceMapRanges(prop, name) + return prop + } + return name.Clone(emitContext.Factory) +} + +func constantExpression(value any, factory *printer.NodeFactory) *ast.Expression { + switch value := value.(type) { + case string: + return factory.NewStringLiteral(value) + case jsnum.Number: + if value.IsInf() || value.IsNaN() { + return nil + } + if value < 0 { + return factory.NewPrefixUnaryExpression(ast.KindMinusToken, constantExpression(-value, factory)) + } + return factory.NewNumericLiteral(value.String()) + } + return nil +} + +func isInstantiatedModule(node *ast.ModuleDeclarationNode, preserveConstEnums bool) bool { + moduleState := ast.GetModuleInstanceState(node) + return moduleState == ast.ModuleInstanceStateInstantiated || + (preserveConstEnums && moduleState == ast.ModuleInstanceStateConstEnumOnly) +} diff --git a/internal/transformers/utilities.go b/internal/transformers/utilities.go index 75bc92bd1d..7559c817a4 100644 --- a/internal/transformers/utilities.go +++ b/internal/transformers/utilities.go @@ -4,40 +4,26 @@ import ( "slices" "github.com/microsoft/typescript-go/internal/ast" - "github.com/microsoft/typescript-go/internal/core" - "github.com/microsoft/typescript-go/internal/jsnum" - "github.com/microsoft/typescript-go/internal/outputpaths" "github.com/microsoft/typescript-go/internal/printer" - "github.com/microsoft/typescript-go/internal/tspath" ) -func isGeneratedIdentifier(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { +func IsGeneratedIdentifier(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { return emitContext.HasAutoGenerateInfo(name) } -func isHelperName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { +func IsHelperName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { return emitContext.EmitFlags(name)&printer.EFHelperName != 0 } -func isLocalName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { +func IsLocalName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { return emitContext.EmitFlags(name)&printer.EFLocalName != 0 } -func isExportName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { +func IsExportName(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { return emitContext.EmitFlags(name)&printer.EFExportName != 0 } -func isDeclarationNameOfEnumOrNamespace(emitContext *printer.EmitContext, node *ast.IdentifierNode) bool { - if original := emitContext.MostOriginal(node); original != nil && original.Parent != nil { - switch original.Parent.Kind { - case ast.KindEnumDeclaration, ast.KindModuleDeclaration: - return original == original.Parent.Name() - } - } - return false -} - -func isIdentifierReference(name *ast.IdentifierNode, parent *ast.Node) bool { +func IsIdentifierReference(name *ast.IdentifierNode, parent *ast.Node) bool { switch parent.Kind { case ast.KindBinaryExpression, ast.KindPrefixUnaryExpression, @@ -127,28 +113,6 @@ func isIdentifierReference(name *ast.IdentifierNode, parent *ast.Node) bool { } } -func constantExpression(value any, factory *printer.NodeFactory) *ast.Expression { - switch value := value.(type) { - case string: - return factory.NewStringLiteral(value) - case jsnum.Number: - if value.IsInf() || value.IsNaN() { - return nil - } - if value < 0 { - return factory.NewPrefixUnaryExpression(ast.KindMinusToken, constantExpression(-value, factory)) - } - return factory.NewNumericLiteral(value.String()) - } - return nil -} - -func isInstantiatedModule(node *ast.ModuleDeclarationNode, preserveConstEnums bool) bool { - moduleState := ast.GetModuleInstanceState(node) - return moduleState == ast.ModuleInstanceStateInstantiated || - (preserveConstEnums && moduleState == ast.ModuleInstanceStateConstEnumOnly) -} - func convertBindingElementToArrayAssignmentElement(emitContext *printer.EmitContext, element *ast.BindingElement) *ast.Expression { if element.Name() == nil { elision := emitContext.Factory.NewOmittedExpression() @@ -206,7 +170,7 @@ func convertBindingElementToObjectAssignmentElement(emitContext *printer.EmitCon return assignment } -func convertBindingPatternToAssignmentPattern(emitContext *printer.EmitContext, element *ast.BindingPattern) *ast.Expression { +func ConvertBindingPatternToAssignmentPattern(emitContext *printer.EmitContext, element *ast.BindingPattern) *ast.Expression { switch element.Kind { case ast.KindArrayBindingPattern: return convertBindingElementToArrayAssignmentPattern(emitContext, element) @@ -245,12 +209,12 @@ func convertBindingElementToArrayAssignmentPattern(emitContext *printer.EmitCont func convertBindingNameToAssignmentElementTarget(emitContext *printer.EmitContext, element *ast.Node) *ast.Expression { if ast.IsBindingPattern(element) { - return convertBindingPatternToAssignmentPattern(emitContext, element.AsBindingPattern()) + return ConvertBindingPatternToAssignmentPattern(emitContext, element.AsBindingPattern()) } return element } -func convertVariableDeclarationToAssignmentExpression(emitContext *printer.EmitContext, element *ast.VariableDeclaration) *ast.Expression { +func ConvertVariableDeclarationToAssignmentExpression(emitContext *printer.EmitContext, element *ast.VariableDeclaration) *ast.Expression { if element.Initializer == nil { return nil } @@ -261,164 +225,9 @@ func convertVariableDeclarationToAssignmentExpression(emitContext *printer.EmitC return assignment } -func convertEntityNameToExpression(emitContext *printer.EmitContext, name *ast.EntityName) *ast.Expression { - if ast.IsQualifiedName(name) { - left := convertEntityNameToExpression(emitContext, name.AsQualifiedName().Left) - right := name.AsQualifiedName().Right - prop := emitContext.Factory.NewPropertyAccessExpression(left, nil /*questionDotToken*/, right, ast.NodeFlagsNone) - emitContext.SetOriginal(prop, name) - emitContext.AssignCommentAndSourceMapRanges(prop, name) - return prop - } - return name.Clone(emitContext.Factory) -} - -// Get the name of a target module from an import/export declaration as should be written in the emitted output. -// The emitted output name can be different from the input if: -// 1. The module has a /// -// 2. --out or --outFile is used, making the name relative to the rootDir -// 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). -// -// Otherwise, a new StringLiteral node representing the module name will be returned. -func getExternalModuleNameLiteral(factory *printer.NodeFactory, importNode *ast.Node /*ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall*/, sourceFile *ast.SourceFile, host any /*EmitHost*/, resolver printer.EmitResolver, compilerOptions *core.CompilerOptions) *ast.StringLiteralNode { - moduleName := ast.GetExternalModuleName(importNode) - if moduleName != nil && ast.IsStringLiteral(moduleName) { - name := tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) - if name == nil { - name = tryRenameExternalModule(factory, moduleName, sourceFile) - } - if name == nil { - name = factory.NewStringLiteral(moduleName.Text()) - } - return name - } - return nil -} - -// Get the name of a module as should be written in the emitted output. -// The emitted output name can be different from the input if: -// 1. The module has a /// -// 2. --out or --outFile is used, making the name relative to the rootDir -// -// Otherwise, a new StringLiteral node representing the module name will be returned. -func tryGetModuleNameFromFile(factory *printer.NodeFactory, file *ast.SourceFile, host any /*EmitHost*/, options *core.CompilerOptions) *ast.StringLiteralNode { - if file == nil { - return nil - } - // !!! - // if file.moduleName { - // return factory.createStringLiteral(file.moduleName) - // } - if !file.IsDeclarationFile && len(options.OutFile) > 0 { - return factory.NewStringLiteral(getExternalModuleNameFromPath(host, file.FileName(), "" /*referencePath*/)) - } - return nil -} - -func tryGetModuleNameFromDeclaration(declaration *ast.Node /*ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall*/, host any /*EmitHost*/, factory *printer.NodeFactory, resolver printer.EmitResolver, compilerOptions *core.CompilerOptions) *ast.StringLiteralNode { - if resolver == nil { - return nil - } - return tryGetModuleNameFromFile(factory, resolver.GetExternalModuleFileFromDeclaration(declaration), host, compilerOptions) -} - -// Resolves a local path to a path which is absolute to the base of the emit -func getExternalModuleNameFromPath(host any /*ResolveModuleNameResolutionHost*/, fileName string, referencePath string) string { - // !!! - return "" -} - -// Some bundlers (SystemJS builder) sometimes want to rename dependencies. -// Here we check if alternative name was provided for a given moduleName and return it if possible. -func tryRenameExternalModule(factory *printer.NodeFactory, moduleName *ast.LiteralExpression, sourceFile *ast.SourceFile) *ast.StringLiteralNode { - // !!! - return nil -} - -func rewriteModuleSpecifier(emitContext *printer.EmitContext, node *ast.Expression, compilerOptions *core.CompilerOptions) *ast.Expression { - if node == nil || !ast.IsStringLiteral(node) || !core.ShouldRewriteModuleSpecifier(node.Text(), compilerOptions) { - return node - } - updatedText := tspath.ChangeExtension(node.Text(), outputpaths.GetOutputExtension(node.Text(), compilerOptions.Jsx)) - if updatedText != node.Text() { - updated := emitContext.Factory.NewStringLiteral(updatedText) - // !!! set quote style - emitContext.SetOriginal(updated, node) - emitContext.AssignCommentAndSourceMapRanges(updated, node) - return updated - } - return node -} - -func singleOrMany(nodes []*ast.Node, factory *printer.NodeFactory) *ast.Node { +func SingleOrMany(nodes []*ast.Node, factory *printer.NodeFactory) *ast.Node { if len(nodes) == 1 { return nodes[0] } return factory.NewSyntaxList(nodes) } - -func isFileLevelReservedGeneratedIdentifier(emitContext *printer.EmitContext, name *ast.IdentifierNode) bool { - info := emitContext.GetAutoGenerateInfo(name) - return info != nil && - info.Flags.IsFileLevel() && - info.Flags.IsOptimistic() && - info.Flags.IsReservedInNestedScopes() -} - -func createEmptyImports(factory *printer.NodeFactory) *ast.Statement { - return factory.NewExportDeclaration( - nil, /*modifiers*/ - false, /*isTypeOnly*/ - factory.NewNamedExports(factory.NewNodeList(nil)), - nil, /*moduleSpecifier*/ - nil, /*attributes*/ - ) -} - -// Used in the module transformer to check if an expression is reasonably without sideeffect, -// -// and thus better to copy into multiple places rather than to cache in a temporary variable -// - this is mostly subjective beyond the requirement that the expression not be sideeffecting -func isSimpleCopiableExpression(expression *ast.Expression) bool { - return ast.IsStringLiteralLike(expression) || - ast.IsNumericLiteral(expression) || - ast.IsKeywordKind(expression.Kind) || - ast.IsIdentifier(expression) -} - -// A simple inlinable expression is an expression which can be copied into multiple locations -// without risk of repeating any sideeffects and whose value could not possibly change between -// any such locations -func isSimpleInlineableExpression(expression *ast.Expression) bool { - return !ast.IsIdentifier(expression) && isSimpleCopiableExpression(expression) -} - -func convertClassDeclarationToClassExpression(emitContext *printer.EmitContext, node *ast.ClassDeclaration) *ast.Expression { - updated := emitContext.Factory.NewClassExpression( - extractModifiers(emitContext, node.Modifiers(), ^ast.ModifierFlagsExportDefault), - node.Name(), - node.TypeParameters, - node.HeritageClauses, - node.Members, - ) - emitContext.SetOriginal(updated, node.AsNode()) - updated.Loc = node.Loc - return updated -} - -func createExpressionFromEntityName(factory ast.NodeFactoryCoercible, node *ast.Node) *ast.Expression { - if ast.IsQualifiedName(node) { - left := createExpressionFromEntityName(factory, node.AsQualifiedName().Left) - // TODO(rbuckton): Does this need to be parented? - right := node.AsQualifiedName().Right.Clone(factory.AsNodeFactory()) - right.Loc = node.AsQualifiedName().Right.Loc - right.Parent = node.AsQualifiedName().Right.Parent - return factory.AsNodeFactory().NewPropertyAccessExpression(left, nil, right, ast.NodeFlagsNone) - } else { - // TODO(rbuckton): Does this need to be parented? - res := node.Clone(factory.AsNodeFactory()) - res.Loc = node.Loc - res.Parent = node.Parent - return res - } -}