Skip to content

Commit ccb2338

Browse files
authored
Fix for export detection of shadowed names (#387)
fixes #385 Symbols are now used directly when determing if identifiers should be exported instead of just using their string name.
1 parent 62a4692 commit ccb2338

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

src/LuaTransformer.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,25 +3170,41 @@ export class LuaTransformer {
31703170
}
31713171

31723172
public transformIdentifierExpression(expression: ts.Identifier): tstl.IdentifierOrTableIndexExpression {
3173-
if (this.isIdentifierExported(expression.escapedText)) {
3174-
return this.createExportedIdentifier(this.transformIdentifier(expression));
3173+
const identifier = this.transformIdentifier(expression);
3174+
if (this.isIdentifierExported(identifier)) {
3175+
return this.createExportedIdentifier(identifier);
31753176
}
3176-
return this.transformIdentifier(expression);
3177+
return identifier;
31773178
}
31783179

3179-
public isIdentifierExported(identifierName: string | ts.__String): boolean {
3180+
public isIdentifierExported(identifier: tstl.Identifier): boolean {
31803181
if (!this.isModule && !this.currentNamespace) {
31813182
return false;
31823183
}
3184+
3185+
const symbolInfo = identifier.symbolId && this.symbolInfo.get(identifier.symbolId);
3186+
if (!symbolInfo) {
3187+
return false;
3188+
}
3189+
31833190
const currentScope = this.currentNamespace ? this.currentNamespace : this.currentSourceFile;
31843191
const scopeSymbol = this.checker.getSymbolAtLocation(currentScope)
31853192
? this.checker.getSymbolAtLocation(currentScope)
31863193
: this.checker.getTypeAtLocation(currentScope).getSymbol();
3187-
return scopeSymbol.exports.has(identifierName as ts.__String);
3194+
3195+
const it: Iterable<ts.Symbol> = {
3196+
[Symbol.iterator]: () => scopeSymbol.exports.values(), // Why isn't ts.SymbolTable.values() iterable?
3197+
};
3198+
for (const symbol of it) {
3199+
if (symbol === symbolInfo.symbol) {
3200+
return true;
3201+
}
3202+
}
3203+
return false;
31883204
}
31893205

31903206
public addExportToIdentifier(identifier: tstl.Identifier): tstl.IdentifierOrTableIndexExpression {
3191-
if (this.isIdentifierExported(identifier.text)) {
3207+
if (this.isIdentifierExported(identifier)) {
31923208
return this.createExportedIdentifier(identifier);
31933209
}
31943210
return identifier;
@@ -3292,9 +3308,9 @@ export class LuaTransformer {
32923308
return false;
32933309
}
32943310
if (Array.isArray(identifier)) {
3295-
return identifier.some(i => this.isIdentifierExported(i.text));
3311+
return identifier.some(i => this.isIdentifierExported(i));
32963312
} else {
3297-
return this.isIdentifierExported(identifier.text);
3313+
return this.isIdentifierExported(identifier);
32983314
}
32993315
}
33003316

@@ -3481,6 +3497,16 @@ export class LuaTransformer {
34813497
const symbol = this.checker.getSymbolAtLocation(identifier);
34823498
let symbolId: number | undefined;
34833499
if (symbol) {
3500+
// Track first time symbols are seen
3501+
if (!this.symbolIds.has(symbol)) {
3502+
symbolId = this.genSymbolIdCounter++;
3503+
const symbolInfo: SymbolInfo = {symbol, firstSeenAtPos: identifier.pos};
3504+
this.symbolIds.set(symbol, symbolId);
3505+
this.symbolInfo.set(symbolId, symbolInfo);
3506+
} else {
3507+
symbolId = this.symbolIds.get(symbol);
3508+
}
3509+
34843510
if (this.options.noHoisting) {
34853511
// Check for reference-before-declaration
34863512
const declaration = tsHelper.getFirstDeclaration(symbol, this.currentSourceFile);
@@ -3489,16 +3515,6 @@ export class LuaTransformer {
34893515
}
34903516

34913517
} else {
3492-
// Track first time symbols are seen
3493-
if (!this.symbolIds.has(symbol)) {
3494-
symbolId = this.genSymbolIdCounter++;
3495-
const symbolInfo: SymbolInfo = {symbol, firstSeenAtPos: identifier.pos};
3496-
this.symbolIds.set(symbol, symbolId);
3497-
this.symbolInfo.set(symbolId, symbolInfo);
3498-
} else {
3499-
symbolId = this.symbolIds.get(symbol);
3500-
}
3501-
35023518
//Mark symbol as seen in all current scopes
35033519
this.scopeStack.forEach(s => {
35043520
if (!s.referencedSymbols) { s.referencedSymbols = new Set(); }

test/unit/functions.spec.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Expect, Test, TestCase, FocusTest } from "alsatian";
1+
import { Expect, Test, TestCase } from "alsatian";
22

33
import * as ts from "typescript";
44
import * as util from "../src/util";
@@ -388,4 +388,15 @@ export class FunctionTests {
388388
const result = util.transpileAndExecute(code);
389389
Expect(result).toBe("foobar");
390390
}
391+
392+
@Test("Function local overriding export")
393+
public functionLocalOverridingExport(): void {
394+
const code =
395+
`export const foo = 5;
396+
function bar(foo: number) {
397+
return foo;
398+
}
399+
export const result = bar(7);`;
400+
Expect(util.transpileExecuteAndReturnExport(code, "result")).toBe(7);
401+
}
391402
}

0 commit comments

Comments
 (0)