Skip to content

Commit 8504525

Browse files
ark120202Perryvw
authored andcommitted
Fix function hoisting with synthetic source file (#807)
1 parent c920bb3 commit 8504525

File tree

5 files changed

+34
-15
lines changed

5 files changed

+34
-15
lines changed

src/transformation/context/visitors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ type NodesBySyntaxKind = {
133133
[ts.SyntaxKind.NullKeyword]: ts.NullLiteral;
134134
[ts.SyntaxKind.SuperKeyword]: ts.SuperExpression;
135135
[ts.SyntaxKind.ThisKeyword]: ts.ThisExpression;
136+
[ts.SyntaxKind.NotEmittedStatement]: ts.NotEmittedStatement;
136137
};
137138

138139
export type ExpressionLikeNode = ts.Expression | ts.QualifiedName | ts.ExternalModuleReference;

src/transformation/utils/typescript/index.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,12 @@ export function findFirstNodeAbove<T extends ts.Node>(node: ts.Node, callback: (
2525
}
2626

2727
export function getFirstDeclarationInFile(symbol: ts.Symbol, sourceFile: ts.SourceFile): ts.Declaration | undefined {
28-
const declarations = (symbol.getDeclarations() ?? []).filter(
29-
// TODO: getSourceFile?
30-
declaration => findFirstNodeAbove(declaration, ts.isSourceFile) === sourceFile
31-
);
28+
const originalSourceFile = ts.getParseTreeNode(sourceFile) ?? sourceFile;
29+
const declarations = (symbol.getDeclarations() ?? []).filter(d => d.getSourceFile() === originalSourceFile);
3230

3331
return declarations.length > 0 ? declarations.reduce((p, c) => (p.pos < c.pos ? p : c)) : undefined;
3432
}
3533

36-
export function isFirstDeclaration(context: TransformationContext, node: ts.VariableDeclaration): boolean {
37-
const symbol = context.checker.getSymbolAtLocation(node.name);
38-
if (!symbol) {
39-
return false;
40-
}
41-
42-
const firstDeclaration = getFirstDeclarationInFile(symbol, context.sourceFile);
43-
return firstDeclaration === node;
44-
}
45-
4634
function isStandardLibraryDeclaration(context: TransformationContext, declaration: ts.Declaration): boolean {
4735
const sourceFile = declaration.getSourceFile();
4836
if (!sourceFile) {

src/transformation/visitors/typescript.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ export const typescriptVisitors: Visitors = {
2222
[ts.SyntaxKind.NonNullExpression]: (node, context) => context.transformExpression(node.expression),
2323
[ts.SyntaxKind.AsExpression]: transformAssertionExpression,
2424
[ts.SyntaxKind.TypeAssertionExpression]: transformAssertionExpression,
25+
[ts.SyntaxKind.NotEmittedStatement]: () => undefined,
2526
};

test/unit/hoisting.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@ test("Hoisting due to reference from hoisted function", () => {
109109
expect(result).toBe("foo");
110110
});
111111

112+
test("Hoisting with synthetic source file node", () => {
113+
util.testModule`
114+
export const foo = bar();
115+
function bar() { return "bar"; }
116+
`
117+
.setCustomTransformers({
118+
before: [
119+
() => sourceFile =>
120+
ts.updateSourceFileNode(
121+
sourceFile,
122+
[ts.createNotEmittedStatement(undefined!), ...sourceFile.statements],
123+
sourceFile.isDeclarationFile,
124+
sourceFile.referencedFiles,
125+
sourceFile.typeReferenceDirectives,
126+
sourceFile.hasNoDefaultLib,
127+
sourceFile.libReferenceDirectives
128+
),
129+
],
130+
})
131+
.expectToMatchJsResult();
132+
});
133+
112134
test("Namespace Hoisting", () => {
113135
const code = `
114136
function bar() {

test/util.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ export abstract class TestBuilder {
212212
return this;
213213
}
214214

215+
private customTransformers?: ts.CustomTransformers;
216+
public setCustomTransformers(customTransformers?: ts.CustomTransformers): this {
217+
expect(this.hasProgram).toBe(false);
218+
this.customTransformers = customTransformers;
219+
return this;
220+
}
221+
215222
// Transpilation and execution
216223

217224
public getTsCode(): string {
@@ -228,7 +235,7 @@ export abstract class TestBuilder {
228235
@memoize
229236
public getLuaResult(): tstl.TranspileResult {
230237
const program = this.getProgram();
231-
const result = tstl.transpile({ program });
238+
const result = tstl.transpile({ program, customTransformers: this.customTransformers });
232239
const diagnostics = ts.sortAndDeduplicateDiagnostics([
233240
...ts.getPreEmitDiagnostics(program),
234241
...result.diagnostics,

0 commit comments

Comments
 (0)