vendor tsgo
This commit is contained in:
153
tools/tsgo/internal/transformers/tstransforms/importelision.go
Normal file
153
tools/tsgo/internal/transformers/tstransforms/importelision.go
Normal file
@@ -0,0 +1,153 @@
|
||||
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 {
|
||||
transformers.Transformer
|
||||
compilerOptions *core.CompilerOptions
|
||||
currentSourceFile *ast.SourceFile
|
||||
emitResolver printer.EmitResolver
|
||||
}
|
||||
|
||||
func NewImportElisionTransformer(opt *transformers.TransformOptions) *transformers.Transformer {
|
||||
compilerOptions := opt.CompilerOptions
|
||||
emitContext := opt.Context
|
||||
if compilerOptions.VerbatimModuleSyntax.IsTrue() {
|
||||
panic("ImportElisionTransformer should not be used with VerbatimModuleSyntax")
|
||||
}
|
||||
tx := &ImportElisionTransformer{compilerOptions: compilerOptions, emitResolver: opt.EmitResolver}
|
||||
return tx.NewTransformer(tx.visit, emitContext)
|
||||
}
|
||||
|
||||
func (tx *ImportElisionTransformer) visit(node *ast.Node) *ast.Node {
|
||||
if ast.IsSourceFile(node) && tx.emitResolver != nil {
|
||||
tx.emitResolver.MarkLinkedReferencesRecursively(tx.EmitContext().MostOriginal(node).AsSourceFile())
|
||||
}
|
||||
|
||||
switch node.Kind {
|
||||
case ast.KindImportEqualsDeclaration:
|
||||
if ast.IsExternalModuleImportEqualsDeclaration(node) {
|
||||
if !tx.shouldEmitAliasDeclaration(node) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if !tx.shouldEmitImportEqualsDeclaration(node.AsImportEqualsDeclaration()) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return tx.Visitor().VisitEachChild(node)
|
||||
case ast.KindImportDeclaration:
|
||||
n := node.AsImportDeclaration()
|
||||
// Do not elide a side-effect only import declaration.
|
||||
// import "foo";
|
||||
if n.ImportClause != nil {
|
||||
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.Visitor().VisitEachChild(node)
|
||||
case ast.KindImportClause:
|
||||
n := node.AsImportClause()
|
||||
name := core.IfElse(tx.shouldEmitAliasDeclaration(node), n.Name(), nil)
|
||||
namedBindings := tx.Visitor().VisitNode(n.NamedBindings)
|
||||
if name == nil && namedBindings == nil {
|
||||
// all import bindings were elided
|
||||
return nil
|
||||
}
|
||||
return tx.Factory().UpdateImportClause(n, n.PhaseModifier, name, namedBindings)
|
||||
case ast.KindNamespaceImport:
|
||||
if !tx.shouldEmitAliasDeclaration(node) {
|
||||
// elide unused imports
|
||||
return nil
|
||||
}
|
||||
return node
|
||||
case ast.KindNamedImports:
|
||||
n := node.AsNamedImports()
|
||||
elements := tx.Visitor().VisitNodes(n.Elements)
|
||||
if len(elements.Nodes) == 0 {
|
||||
// all import specifiers were elided
|
||||
return nil
|
||||
}
|
||||
return tx.Factory().UpdateNamedImports(n, elements)
|
||||
case ast.KindImportSpecifier:
|
||||
if !tx.shouldEmitAliasDeclaration(node) {
|
||||
// elide type-only or unused imports
|
||||
return nil
|
||||
}
|
||||
return node
|
||||
case ast.KindExportAssignment:
|
||||
if !tx.compilerOptions.VerbatimModuleSyntax.IsTrue() && !tx.isValueAliasDeclaration(node) {
|
||||
// elide unused import
|
||||
return nil
|
||||
}
|
||||
return tx.Visitor().VisitEachChild(node)
|
||||
case ast.KindExportDeclaration:
|
||||
n := node.AsExportDeclaration()
|
||||
var exportClause *ast.Node
|
||||
if n.ExportClause != nil {
|
||||
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))
|
||||
case ast.KindNamedExports:
|
||||
n := node.AsNamedExports()
|
||||
elements := tx.Visitor().VisitNodes(n.Elements)
|
||||
if len(elements.Nodes) == 0 {
|
||||
// all export specifiers were elided
|
||||
return nil
|
||||
}
|
||||
return tx.Factory().UpdateNamedExports(n, elements)
|
||||
case ast.KindExportSpecifier:
|
||||
if !tx.isValueAliasDeclaration(node) {
|
||||
// elide unused export
|
||||
return nil
|
||||
}
|
||||
return node
|
||||
case ast.KindSourceFile:
|
||||
savedCurrentSourceFile := tx.currentSourceFile
|
||||
tx.currentSourceFile = node.AsSourceFile()
|
||||
node = tx.Visitor().VisitEachChild(node)
|
||||
tx.currentSourceFile = savedCurrentSourceFile
|
||||
return node
|
||||
case ast.KindModuleDeclaration, ast.KindModuleBlock:
|
||||
return tx.Visitor().VisitEachChild(node)
|
||||
default:
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *ImportElisionTransformer) shouldEmitAliasDeclaration(node *ast.Node) bool {
|
||||
return ast.IsInJSFile(node) || tx.isReferencedAliasDeclaration(node)
|
||||
}
|
||||
|
||||
func (tx *ImportElisionTransformer) shouldEmitImportEqualsDeclaration(node *ast.ImportEqualsDeclaration) bool {
|
||||
// preserve old compiler's behavior: emit import declaration (even if we do not consider them referenced) when
|
||||
// - current file is not external module
|
||||
// - import declaration is top level and target is value imported by entity name
|
||||
return tx.shouldEmitAliasDeclaration(node.AsNode()) || (!ast.IsExternalModule(tx.currentSourceFile) && tx.isTopLevelValueImportEqualsWithEntityName(node.AsNode()))
|
||||
}
|
||||
|
||||
func (tx *ImportElisionTransformer) isReferencedAliasDeclaration(node *ast.Node) bool {
|
||||
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)
|
||||
return node == nil || tx.emitResolver.IsValueAliasDeclaration(node)
|
||||
}
|
||||
|
||||
func (tx *ImportElisionTransformer) isTopLevelValueImportEqualsWithEntityName(node *ast.Node) bool {
|
||||
node = tx.EmitContext().ParseNode(node)
|
||||
return node != nil && tx.emitResolver.IsTopLevelValueImportEqualsWithEntityName(node)
|
||||
}
|
||||
Reference in New Issue
Block a user