Skip to content

Commit 2dc28fb

Browse files
authored
fix broken customName interaction with import statements (#1654)
1 parent 5acd109 commit 2dc28fb

File tree

5 files changed

+89
-6
lines changed

5 files changed

+89
-6
lines changed

src/transformation/visitors/access.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export function transformPropertyAccessExpressionWithCapture(
115115

116116
let property = node.name.text;
117117
const symbol = context.checker.getSymbolAtLocation(node.name);
118-
const customName = getCustomNameFromSymbol(symbol);
118+
const customName = getCustomNameFromSymbol(context, symbol);
119119
if (customName) {
120120
property = customName;
121121
}

src/transformation/visitors/call.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export function transformContextualCallExpression(
138138
let name = left.name.text;
139139

140140
const symbol = context.checker.getSymbolAtLocation(left);
141-
const customName = getCustomNameFromSymbol(symbol);
141+
const customName = getCustomNameFromSymbol(context, symbol);
142142

143143
if (customName) {
144144
name = customName;

src/transformation/visitors/identifier.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function transformIdentifier(context: TransformationContext, identifier:
1818
return transformNonValueIdentifier(context, identifier, context.checker.getSymbolAtLocation(identifier));
1919
}
2020

21-
export function getCustomNameFromSymbol(symbol?: ts.Symbol): undefined | string {
21+
export function getCustomNameFromSymbol(context: TransformationContext, symbol?: ts.Symbol): undefined | string {
2222
let retVal: undefined | string;
2323

2424
if (symbol) {
@@ -33,6 +33,18 @@ export function getCustomNameFromSymbol(symbol?: ts.Symbol): undefined | string
3333
customNameAnnotation = foundAnnotation;
3434
break;
3535
}
36+
37+
// If the symbol is an imported value, check the original declaration
38+
// beware of declaration.propertyName, this is the import name alias and should not be renamed!
39+
if (ts.isImportSpecifier(declaration) && !declaration.propertyName) {
40+
const importedType = context.checker.getTypeAtLocation(declaration);
41+
if (importedType.symbol) {
42+
const importedCustomName = getCustomNameFromSymbol(context, importedType.symbol);
43+
if (importedCustomName) {
44+
return importedCustomName;
45+
}
46+
}
47+
}
3648
}
3749

3850
if (customNameAnnotation) {
@@ -82,7 +94,7 @@ function transformNonValueIdentifier(
8294

8395
let text = hasUnsafeIdentifierName(context, identifier, symbol) ? createSafeName(identifier.text) : identifier.text;
8496

85-
const customName = getCustomNameFromSymbol(symbol);
97+
const customName = getCustomNameFromSymbol(context, symbol);
8698
if (customName) text = customName;
8799

88100
const symbolId = getIdentifierSymbolId(context, identifier, symbol);

src/transformation/visitors/modules/import.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { createHoistableVariableDeclarationStatement } from "../../utils/lua-ast
99
import { importLuaLibFeature, LuaLibFeature } from "../../utils/lualib";
1010
import { createSafeName } from "../../utils/safe-names";
1111
import { peekScope } from "../../utils/scope";
12-
import { transformIdentifier } from "../identifier";
12+
import { getCustomNameFromSymbol, transformIdentifier } from "../identifier";
1313
import { transformPropertyName } from "../literal";
1414

1515
function isNoResolutionPath(context: TransformationContext, moduleSpecifier: ts.Expression): boolean {
@@ -46,8 +46,15 @@ function transformImportSpecifier(
4646
importSpecifier: ts.ImportSpecifier,
4747
moduleTableName: lua.Identifier
4848
): lua.VariableDeclarationStatement {
49+
const type = context.checker.getTypeAtLocation(importSpecifier.name);
50+
4951
const leftIdentifier = transformIdentifier(context, importSpecifier.name);
50-
const propertyName = transformPropertyName(context, importSpecifier.propertyName ?? importSpecifier.name);
52+
53+
// If imported value has a customName annotation use that, otherwise use regular property
54+
const customName = getCustomNameFromSymbol(context, type.getSymbol());
55+
const propertyName = customName
56+
? lua.createStringLiteral(customName, importSpecifier.propertyName ?? importSpecifier.name)
57+
: transformPropertyName(context, importSpecifier.propertyName ?? importSpecifier.name);
5158

5259
return lua.createVariableDeclarationStatement(
5360
leftIdentifier,

test/unit/identifiers.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,3 +991,67 @@ test("customName rename declared function", () => {
991991
expect(mainFile.lua).toContain("Test2(");
992992
expect(mainFile.lua).not.toContain("Test(");
993993
});
994+
995+
test("customName rename import specifier", () => {
996+
const testModule = util.testModule`
997+
import { Test } from "./myimport";
998+
import { Test as Aliased } from "./myimport";
999+
Test();
1000+
Aliased();
1001+
`.addExtraFile(
1002+
"myimport.ts",
1003+
`
1004+
/** @customName Test2 **/
1005+
export function Test(this: void): void {}
1006+
`
1007+
);
1008+
1009+
testModule.expectToHaveNoDiagnostics();
1010+
const result = testModule.getLuaResult();
1011+
expect(result.transpiledFiles).not.toHaveLength(0);
1012+
1013+
const mainFile = result.transpiledFiles.find(f => f.outPath === "main.lua");
1014+
expect(mainFile).toBeDefined();
1015+
1016+
// avoid ts error "not defined", even though toBeDefined is being checked above
1017+
if (!mainFile) return;
1018+
1019+
expect(mainFile.lua).toBeDefined();
1020+
expect(mainFile.lua).toContain("Test2(");
1021+
expect(mainFile.lua).toContain("myimport.Test2");
1022+
expect(mainFile.lua).not.toContain("Test(");
1023+
1024+
testModule.expectNoExecutionError();
1025+
});
1026+
1027+
test("customName import specifier from declarations", () => {
1028+
const testModule = util.testModule`
1029+
import { Test } from "./myimport";
1030+
import { Test as Aliased } from "./myimport";
1031+
Test();
1032+
Aliased();
1033+
`
1034+
.addExtraFile(
1035+
"myimport.d.ts",
1036+
`
1037+
/** @customName Test2 **/
1038+
export declare function Test(this: void): void;
1039+
`
1040+
)
1041+
.setOptions({ noResolvePaths: ["./myimport"] });
1042+
1043+
testModule.expectToHaveNoDiagnostics();
1044+
const result = testModule.getLuaResult();
1045+
expect(result.transpiledFiles).not.toHaveLength(0);
1046+
1047+
const mainFile = result.transpiledFiles.find(f => f.outPath === "main.lua");
1048+
expect(mainFile).toBeDefined();
1049+
1050+
// avoid ts error "not defined", even though toBeDefined is being checked above
1051+
if (!mainFile) return;
1052+
1053+
expect(mainFile.lua).toBeDefined();
1054+
expect(mainFile.lua).toContain("Test2(");
1055+
expect(mainFile.lua).toContain("myimport.Test2");
1056+
expect(mainFile.lua).not.toContain("Test(");
1057+
});

0 commit comments

Comments
 (0)