Skip to content

Commit e6a6025

Browse files
committed
transform expando hosts
1 parent c771636 commit e6a6025

23 files changed

+236
-734
lines changed

internal/transformers/declarations/transform.go

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/microsoft/typescript-go/internal/ast"
7+
"github.com/microsoft/typescript-go/internal/collections"
78
"github.com/microsoft/typescript-go/internal/core"
89
"github.com/microsoft/typescript-go/internal/debug"
910
"github.com/microsoft/typescript-go/internal/diagnostics"
@@ -58,13 +59,14 @@ type DeclarationTransformer struct {
5859
declarationMapPath string
5960

6061
isBundledEmit bool
61-
declareModifier DeclareModifier
62+
needsDeclare bool
6263
needsScopeFixMarker bool
6364
resultHasScopeMarker bool
6465
enclosingDeclaration *ast.Node
6566
resultHasExternalModuleIndicator bool
6667
suppressNewDiagnosticContexts bool
6768
lateStatementReplacementMap map[ast.NodeId]*ast.Node
69+
expandoHosts collections.Set[ast.NodeId]
6870
rawReferencedFiles []ReferencedFilePair
6971
rawTypeReferenceDirectives []*ast.FileReference
7072
rawLibReferenceDirectives []*ast.FileReference
@@ -167,7 +169,7 @@ func (tx *DeclarationTransformer) visitSourceFile(node *ast.SourceFile) *ast.Nod
167169
}
168170

169171
tx.isBundledEmit = false
170-
tx.declareModifier = DeclareModifierEligible
172+
tx.needsDeclare = true
171173
tx.needsScopeFixMarker = false
172174
tx.resultHasScopeMarker = false
173175
tx.enclosingDeclaration = node.AsNode()
@@ -176,6 +178,7 @@ func (tx *DeclarationTransformer) visitSourceFile(node *ast.SourceFile) *ast.Nod
176178
tx.suppressNewDiagnosticContexts = false
177179
tx.state.lateMarkedStatements = make([]*ast.Node, 0)
178180
tx.lateStatementReplacementMap = make(map[ast.NodeId]*ast.Node)
181+
tx.expandoHosts = collections.Set[ast.NodeId]{}
179182
tx.rawReferencedFiles = make([]ReferencedFilePair, 0)
180183
tx.rawTypeReferenceDirectives = make([]*ast.FileReference, 0)
181184
tx.rawLibReferenceDirectives = make([]*ast.FileReference, 0)
@@ -241,16 +244,12 @@ func (tx *DeclarationTransformer) transformAndReplaceLatePaintedStatements(state
241244
next := tx.state.lateMarkedStatements[0]
242245
tx.state.lateMarkedStatements = tx.state.lateMarkedStatements[1:]
243246

244-
saveDeclareModifier := tx.declareModifier
245-
tx.declareModifier = core.IfElse(
246-
next.Parent != nil && ast.IsSourceFile(next.Parent) && !(ast.IsExternalModule(next.Parent.AsSourceFile()) && tx.isBundledEmit),
247-
DeclareModifierEligible,
248-
DeclareModifierNone,
249-
)
247+
saveNeedsDeclare := tx.needsDeclare
248+
tx.needsDeclare = next.Parent != nil && ast.IsSourceFile(next.Parent) && !(ast.IsExternalModule(next.Parent.AsSourceFile()) && tx.isBundledEmit)
250249

251250
result := tx.transformTopLevelDeclaration(next)
252251

253-
tx.declareModifier = saveDeclareModifier
252+
tx.needsDeclare = saveNeedsDeclare
254253
original := tx.EmitContext().MostOriginal(next)
255254
id := ast.GetNodeId(original)
256255
tx.lateStatementReplacementMap[id] = result
@@ -954,7 +953,7 @@ func (tx *DeclarationTransformer) visitDeclarationStatements(input *ast.Node) *a
954953
varDecl := tx.Factory().NewVariableDeclaration(newId, nil, type_, nil)
955954
tx.tracker.PopErrorFallbackNode()
956955
var modList *ast.ModifierList
957-
if tx.declareModifier == DeclareModifierEligible {
956+
if tx.needsDeclare {
958957
modList = tx.Factory().NewModifierList([]*ast.Node{tx.Factory().NewModifier(ast.KindDeclareKeyword)})
959958
} else {
960959
modList = tx.Factory().NewModifierList([]*ast.Node{})
@@ -1112,7 +1111,7 @@ func (tx *DeclarationTransformer) transformTopLevelDeclaration(input *ast.Node)
11121111
if canProdiceDiagnostic {
11131112
tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input)
11141113
}
1115-
saveDeclareModifier := tx.declareModifier
1114+
saveNeedsDeclare := tx.needsDeclare
11161115

11171116
var result *ast.Node
11181117
switch input.Kind {
@@ -1137,13 +1136,13 @@ func (tx *DeclarationTransformer) transformTopLevelDeclaration(input *ast.Node)
11371136

11381137
tx.enclosingDeclaration = previousEnclosingDeclaration
11391138
tx.state.getSymbolAccessibilityDiagnostic = oldDiag
1140-
tx.declareModifier = saveDeclareModifier
1139+
tx.needsDeclare = saveNeedsDeclare
11411140
tx.state.errorNameNode = oldName
11421141
return result
11431142
}
11441143

11451144
func (tx *DeclarationTransformer) transformTypeAliasDeclaration(input *ast.TypeAliasDeclaration) *ast.Node {
1146-
tx.declareModifier = DeclareModifierNone
1145+
tx.needsDeclare = false
11471146
return tx.Factory().UpdateTypeAliasDeclaration(
11481147
input,
11491148
tx.ensureModifiers(input.AsNode()),
@@ -1183,8 +1182,8 @@ func (tx *DeclarationTransformer) transformModuleDeclaration(input *ast.ModuleDe
11831182
// It'd be good to collapse those back in the declaration output, but the AST can't represent the
11841183
// `namespace a.b.c` shape for the printer (without using invalid identifier names).
11851184
mods := tx.ensureModifiers(input.AsNode())
1186-
saveDeclareModifier := tx.declareModifier
1187-
tx.declareModifier = DeclareModifierNone
1185+
saveNeedsDeclare := tx.needsDeclare
1186+
tx.needsDeclare = false
11881187
inner := input.Body
11891188
keyword := input.Keyword
11901189
if keyword != ast.KindGlobalKeyword && (input.Name() == nil || !ast.IsStringLiteral(input.Name())) {
@@ -1214,7 +1213,7 @@ func (tx *DeclarationTransformer) transformModuleDeclaration(input *ast.ModuleDe
12141213
}
12151214

12161215
body := tx.Factory().UpdateModuleBlock(inner.AsModuleBlock(), lateStatements)
1217-
tx.declareModifier = saveDeclareModifier
1216+
tx.needsDeclare = saveNeedsDeclare
12181217
tx.needsScopeFixMarker = oldNeedsScopeFix
12191218
tx.resultHasScopeMarker = oldHasScopeFix
12201219

@@ -1363,7 +1362,7 @@ func (tx *DeclarationTransformer) transformClassDeclaration(input *ast.ClassDecl
13631362
nil,
13641363
)
13651364
var mods *ast.ModifierList
1366-
if tx.declareModifier == DeclareModifierEligible {
1365+
if tx.needsDeclare {
13671366
mods = tx.Factory().NewModifierList([]*ast.Node{tx.Factory().NewModifier(ast.KindDeclareKeyword)})
13681367
}
13691368
statement := tx.Factory().NewVariableStatement(
@@ -1508,13 +1507,8 @@ func (tx *DeclarationTransformer) ensureModifiers(node *ast.Node) *ast.ModifierL
15081507
func (tx *DeclarationTransformer) ensureModifierFlags(node *ast.Node) ast.ModifierFlags {
15091508
mask := ast.ModifierFlagsAll ^ (ast.ModifierFlagsPublic | ast.ModifierFlagsAsync | ast.ModifierFlagsOverride) // No async and override modifiers in declaration files
15101509
additions := ast.ModifierFlagsNone
1511-
if tx.declareModifier == DeclareModifierEligible && !isAlwaysType(node) {
1512-
additions = ast.ModifierFlagsAmbient
1513-
}
1514-
if tx.declareModifier == DeclareModifierEnforced {
1510+
if tx.needsDeclare && !isAlwaysType(node) {
15151511
additions = ast.ModifierFlagsAmbient
1516-
mask ^= ast.ModifierFlagsDefault
1517-
mask ^= ast.ModifierFlagsExport
15181512
}
15191513
parentIsFile := node.Parent.Kind == ast.KindSourceFile
15201514
if !parentIsFile || (tx.isBundledEmit && parentIsFile && ast.IsExternalModule(node.Parent.AsSourceFile())) {
@@ -1901,38 +1895,90 @@ func (tx *DeclarationTransformer) transformExpandoAssignment(node *ast.BinaryExp
19011895
statements = append(statements, tx.Factory().NewExportDeclaration(nil /*modifiers*/, false /*isTypeOnly*/, namedExports, nil /*moduleSpecifier*/, nil /*attributes*/))
19021896
}
19031897

1898+
tx.transformExpandoHost(name, declaration)
1899+
1900+
flags := tx.host.GetEffectiveDeclarationFlags(tx.EmitContext().ParseNode(declaration), ast.ModifierFlagsAll)
19041901
modifierFlags := ast.ModifierFlagsAmbient
1905-
replacement := make([]*ast.Node, 0)
19061902

1907-
flags := ast.GetCombinedModifierFlags(declaration)
19081903
if flags&ast.ModifierFlagsExport != 0 {
1909-
if flags&ast.ModifierFlagsDefault != 0 {
1910-
if n := tx.transformExpandoHost(name, declaration); n != nil {
1911-
replacement = append(replacement, n)
1912-
}
1913-
} else {
1904+
if flags&ast.ModifierFlagsDefault == 0 {
19141905
modifierFlags |= ast.ModifierFlagsExport
19151906
}
19161907
tx.resultHasScopeMarker = true
19171908
tx.resultHasExternalModuleIndicator = true
19181909
}
19191910

1911+
return tx.Factory().NewModuleDeclaration(tx.Factory().NewModifierList(ast.CreateModifiersFromModifierFlags(modifierFlags, tx.Factory().NewModifier)), ast.KindNamespaceKeyword, name, tx.Factory().NewModuleBlock(tx.Factory().NewNodeList(statements)))
1912+
}
1913+
1914+
func (tx *DeclarationTransformer) transformExpandoHost(name *ast.Node, declaration *ast.Declaration) {
1915+
root := core.IfElse(ast.IsVariableDeclaration(declaration), declaration.Parent.Parent, declaration)
1916+
id := ast.GetNodeId(tx.EmitContext().MostOriginal(root))
1917+
1918+
if tx.expandoHosts.Has(id) {
1919+
return
1920+
}
1921+
1922+
saveNeedsDeclare := tx.needsDeclare
1923+
tx.needsDeclare = true
1924+
1925+
modifierFlags := tx.ensureModifierFlags(root)
1926+
defaultExport := modifierFlags&ast.ModifierFlagsExport != 0 && modifierFlags&ast.ModifierFlagsDefault != 0
1927+
1928+
tx.needsDeclare = saveNeedsDeclare
1929+
1930+
if defaultExport {
1931+
modifierFlags |= ast.ModifierFlagsAmbient
1932+
modifierFlags ^= ast.ModifierFlagsDefault
1933+
modifierFlags ^= ast.ModifierFlagsExport
1934+
}
1935+
19201936
modifiers := tx.Factory().NewModifierList(ast.CreateModifiersFromModifierFlags(modifierFlags, tx.Factory().NewModifier))
1921-
namespace := tx.Factory().NewModuleDeclaration(modifiers, ast.KindNamespaceKeyword, name, tx.Factory().NewModuleBlock(tx.Factory().NewNodeList(statements)))
1937+
replacement := make([]*ast.Node, 0)
19221938

1923-
replacement = append(replacement, namespace)
1924-
return tx.Factory().NewSyntaxList(replacement)
1925-
}
1939+
var typeParameters *ast.TypeParameterList
1940+
var parameters *ast.ParameterList
1941+
var returnType *ast.Node
1942+
var asteriskToken *ast.TokenNode
1943+
1944+
if ast.IsFunctionDeclaration(declaration) {
1945+
fn := declaration.AsFunctionDeclaration()
1946+
typeParameters = tx.ensureTypeParams(fn.AsNode(), fn.TypeParameters)
1947+
parameters = tx.updateParamList(fn.AsNode(), fn.Parameters)
1948+
returnType = tx.ensureType(fn.AsNode(), false)
1949+
asteriskToken = fn.AsteriskToken
1950+
} else if ast.IsVariableDeclaration(declaration) && ast.IsFunctionExpressionOrArrowFunction(declaration.Initializer()) {
1951+
if ast.IsFunctionExpression(declaration.Initializer()) {
1952+
fn := declaration.Initializer().AsFunctionExpression()
1953+
typeParameters = tx.ensureTypeParams(fn.AsNode(), fn.TypeParameters)
1954+
parameters = tx.updateParamList(fn.AsNode(), fn.Parameters)
1955+
returnType = tx.ensureType(fn.AsNode(), false)
1956+
asteriskToken = fn.AsteriskToken
1957+
} else if ast.IsArrowFunction(declaration.Initializer()) {
1958+
fn := declaration.Initializer().AsArrowFunction()
1959+
typeParameters = tx.ensureTypeParams(fn.AsNode(), fn.TypeParameters)
1960+
parameters = tx.updateParamList(fn.AsNode(), fn.Parameters)
1961+
returnType = tx.ensureType(fn.AsNode(), false)
1962+
asteriskToken = fn.AsteriskToken
1963+
} else {
1964+
return
1965+
}
1966+
} else {
1967+
return
1968+
}
19261969

1927-
func (tx *DeclarationTransformer) transformExpandoHost(name *ast.Node, node *ast.Node) *ast.Node {
1928-
id := ast.GetNodeId(tx.EmitContext().MostOriginal(node))
1929-
if tx.lateStatementReplacementMap[id] == nil || ast.HasModifier(tx.lateStatementReplacementMap[id], ast.ModifierFlagsDefault) {
1930-
saveDeclareModifier := tx.declareModifier
1931-
tx.declareModifier = DeclareModifierEnforced
1932-
tx.lateStatementReplacementMap[id] = tx.transformTopLevelDeclaration(node)
1933-
tx.declareModifier = saveDeclareModifier
1970+
if ast.IsFunctionDeclaration(declaration) {
1971+
replacement = append(replacement, tx.Factory().UpdateFunctionDeclaration(root.AsFunctionDeclaration(), modifiers, asteriskToken, root.Name(), typeParameters, parameters, returnType, nil /*fullSignature*/, nil /*body*/))
1972+
} else if ast.IsVariableDeclaration(declaration) {
1973+
replacement = append(replacement, tx.Factory().NewFunctionDeclaration(modifiers, asteriskToken, tx.Factory().NewIdentifier(name.Text()), typeParameters, parameters, returnType, nil /*fullSignature*/, nil /*body*/))
1974+
} else {
1975+
return
1976+
}
19341977

1935-
return tx.Factory().NewExportAssignment(nil /*modifiers*/, false /*isExportEquals*/, nil /*typeNode*/, name)
1978+
if defaultExport {
1979+
replacement = append(replacement, tx.Factory().NewExportAssignment(nil /*modifiers*/, false /*isExportEquals*/, nil /*typeNode*/, name))
19361980
}
1937-
return nil
1981+
1982+
tx.expandoHosts.Add(id)
1983+
tx.lateStatementReplacementMap[id] = tx.Factory().NewSyntaxList(replacement)
19381984
}

testdata/baselines/reference/submodule/compiler/declarationEmitExpandoWithGenericConstraint.js

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,45 +36,8 @@ export interface Rect<p extends Point> {
3636
readonly a: p;
3737
readonly b: p;
3838
}
39-
export declare const Point: {
40-
(x: number, y: number): Point;
41-
zero: () => Point;
42-
};
39+
export declare function Point(x: number, y: number): Point;
4340
export declare const Rect: <p extends Point>(a: p, b: p) => Rect<p>;
4441
export declare namespace Point {
4542
const zero: () => Point;
4643
}
47-
48-
49-
//// [DtsFileErrors]
50-
51-
52-
declarationEmitExpandoWithGenericConstraint.d.ts(1,18): error TS2451: Cannot redeclare block-scoped variable 'Point'.
53-
declarationEmitExpandoWithGenericConstraint.d.ts(9,22): error TS2451: Cannot redeclare block-scoped variable 'Point'.
54-
declarationEmitExpandoWithGenericConstraint.d.ts(14,26): error TS2451: Cannot redeclare block-scoped variable 'Point'.
55-
56-
57-
==== declarationEmitExpandoWithGenericConstraint.d.ts (3 errors) ====
58-
export interface Point {
59-
~~~~~
60-
!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
61-
readonly x: number;
62-
readonly y: number;
63-
}
64-
export interface Rect<p extends Point> {
65-
readonly a: p;
66-
readonly b: p;
67-
}
68-
export declare const Point: {
69-
~~~~~
70-
!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
71-
(x: number, y: number): Point;
72-
zero: () => Point;
73-
};
74-
export declare const Rect: <p extends Point>(a: p, b: p) => Rect<p>;
75-
export declare namespace Point {
76-
~~~~~
77-
!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
78-
const zero: () => Point;
79-
}
80-
Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,15 @@
11
--- old.declarationEmitExpandoWithGenericConstraint.js
22
+++ new.declarationEmitExpandoWithGenericConstraint.js
3-
@@= skipped -37, +37 lines =@@
3+
@@= skipped -35, +35 lines =@@
4+
readonly a: p;
5+
readonly b: p;
46
}
5-
export declare const Point: {
6-
(x: number, y: number): Point;
7+
-export declare const Point: {
8+
- (x: number, y: number): Point;
79
- zero(): Point;
8-
+ zero: () => Point;
9-
};
10+
-};
11+
+export declare function Point(x: number, y: number): Point;
1012
export declare const Rect: <p extends Point>(a: p, b: p) => Rect<p>;
1113
+export declare namespace Point {
1214
+ const zero: () => Point;
13-
+}
14-
+
15-
+
16-
+//// [DtsFileErrors]
17-
+
18-
+
19-
+declarationEmitExpandoWithGenericConstraint.d.ts(1,18): error TS2451: Cannot redeclare block-scoped variable 'Point'.
20-
+declarationEmitExpandoWithGenericConstraint.d.ts(9,22): error TS2451: Cannot redeclare block-scoped variable 'Point'.
21-
+declarationEmitExpandoWithGenericConstraint.d.ts(14,26): error TS2451: Cannot redeclare block-scoped variable 'Point'.
22-
+
23-
+
24-
+==== declarationEmitExpandoWithGenericConstraint.d.ts (3 errors) ====
25-
+ export interface Point {
26-
+ ~~~~~
27-
+!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
28-
+ readonly x: number;
29-
+ readonly y: number;
30-
+ }
31-
+ export interface Rect<p extends Point> {
32-
+ readonly a: p;
33-
+ readonly b: p;
34-
+ }
35-
+ export declare const Point: {
36-
+ ~~~~~
37-
+!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
38-
+ (x: number, y: number): Point;
39-
+ zero: () => Point;
40-
+ };
41-
+ export declare const Rect: <p extends Point>(a: p, b: p) => Rect<p>;
42-
+ export declare namespace Point {
43-
+ ~~~~~
44-
+!!! error TS2451: Cannot redeclare block-scoped variable 'Point'.
45-
+ const zero: () => Point;
46-
+ }
47-
+
15+
+}

0 commit comments

Comments
 (0)