Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0aeed7b

Browse files
authored
Merge pull request #744 from PassiveLogic/kr/fix-nested-struct-name-collision
BridgeJS: Fix name collision for same-named nested structs
2 parents f1f290b + 8a0f54e commit 0aeed7b

11 files changed

Lines changed: 611 additions & 27 deletions

File tree

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ public struct BridgeJSLink {
232232
var structExportEntries: [(js: [String], dts: [String])] = []
233233
for structDefinition in skeleton.structs {
234234
let (jsStruct, dtsType, dtsExportEntry) = try renderExportedStruct(structDefinition)
235-
data.topLevelDtsTypeLines.append(contentsOf: dtsType)
235+
if structDefinition.namespace == nil {
236+
data.topLevelDtsTypeLines.append(contentsOf: dtsType)
237+
}
236238

237239
if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) {
238240
structExportEntries.append((js: jsStruct, dts: dtsExportEntry))
@@ -492,15 +494,15 @@ public struct BridgeJSLink {
492494
printer.write("bjs[\"swift_js_struct_lower_\(structDef.abiName)\"] = function(objectId) {")
493495
printer.indent {
494496
printer.write(
495-
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));"
497+
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));"
496498
)
497499
}
498500
printer.write("}")
499501

500502
printer.write("bjs[\"swift_js_struct_lift_\(structDef.abiName)\"] = function() {")
501503
printer.indent {
502504
printer.write(
503-
"const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lift();"
505+
"const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lift();"
504506
)
505507
printer.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(value);")
506508
}
@@ -1005,7 +1007,7 @@ public struct BridgeJSLink {
10051007
let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry)
10061008
let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs)
10071009
_ = try fragment.printCode(
1008-
[structDef.name],
1010+
[structDef.abiName],
10091011
IntrinsicJSFragment.PrintCodeContext(
10101012
scope: structScope,
10111013
printer: structPrinter,
@@ -1159,10 +1161,10 @@ public struct BridgeJSLink {
11591161
for skeleton in skeletons.compactMap(\.exported) {
11601162
for structDef in skeleton.structs {
11611163
printer.write(
1162-
"const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers();"
1164+
"const \(structDef.abiName)Helpers = __bjs_create\(structDef.abiName)Helpers();"
11631165
)
11641166
printer.write(
1165-
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name) = \(structDef.name)Helpers;"
1167+
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName) = \(structDef.abiName)Helpers;"
11661168
)
11671169
printer.nextLine()
11681170
}
@@ -2616,6 +2618,7 @@ extension BridgeJSLink {
26162618
var functions: [ExportedFunction] = []
26172619
var classes: [ExportedClass] = []
26182620
var enums: [ExportedEnum] = []
2621+
var structs: [ExportedStruct] = []
26192622
var staticProperties: [ExportedProperty] = []
26202623
var functionJsLines: [(name: String, lines: [String])] = []
26212624
var functionDtsLines: [(name: String, lines: [String])] = []
@@ -2664,6 +2667,14 @@ extension BridgeJSLink {
26642667
currentNode.content.classes.append(klass)
26652668
}
26662669

2670+
for structDef in skeleton.structs where structDef.namespace != nil {
2671+
var currentNode = rootNode
2672+
for part in structDef.namespace! {
2673+
currentNode = currentNode.addChild(part)
2674+
}
2675+
currentNode.content.structs.append(structDef)
2676+
}
2677+
26672678
for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace {
26682679
var currentNode = rootNode
26692680
for part in enumDef.namespace! {
@@ -2845,8 +2856,18 @@ extension BridgeJSLink {
28452856
}
28462857
}
28472858

2859+
private func hasExportContent(node: NamespaceNode) -> Bool {
2860+
if !node.content.classDtsLines.isEmpty || !node.content.enumDtsLines.isEmpty
2861+
|| !node.content.functionDtsLines.isEmpty || !node.content.staticProperties.isEmpty
2862+
{
2863+
return true
2864+
}
2865+
return node.children.values.contains(where: { hasExportContent(node: $0) })
2866+
}
2867+
28482868
private func printExportsTypeHierarchy(node: NamespaceNode, printer: CodeFragmentPrinter) {
28492869
for (childName, childNode) in node.children.sorted(by: { $0.key < $1.key }) {
2870+
guard hasExportContent(node: childNode) else { continue }
28502871
printer.write("\(childName): {")
28512872
printer.indent {
28522873
for (_, lines) in childNode.content.classDtsLines.sorted(by: { $0.name < $1.name }) {
@@ -2983,8 +3004,8 @@ extension BridgeJSLink {
29833004
renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String
29843005
) {
29853006
func hasContent(node: NamespaceNode) -> Bool {
2986-
// Enums are always included
2987-
if !node.content.enums.isEmpty {
3007+
// Enums and structs are always included
3008+
if !node.content.enums.isEmpty || !node.content.structs.isEmpty {
29883009
return true
29893010
}
29903011

@@ -3164,6 +3185,23 @@ extension BridgeJSLink {
31643185
}
31653186
}
31663187

3188+
// Generate struct interface definitions
3189+
let sortedStructs = childNode.content.structs.sorted { $0.name < $1.name }
3190+
for structDef in sortedStructs {
3191+
let instanceProps = structDef.properties.filter { !$0.isStatic }
3192+
printer.write("export interface \(structDef.name) {")
3193+
printer.indent {
3194+
for property in instanceProps {
3195+
let tsType = BridgeJSLink.resolveTypeScriptType(
3196+
property.type,
3197+
exportedSkeletons: exportedSkeletons
3198+
)
3199+
printer.write("\(property.name): \(tsType);")
3200+
}
3201+
}
3202+
printer.write("}")
3203+
}
3204+
31673205
// Only include functions and properties when exposeToGlobal is true
31683206
if exposeToGlobal {
31693207
let sortedFunctions = childNode.content.functions.sorted { $0.name < $1.name }
@@ -3610,7 +3648,7 @@ extension BridgeType {
36103648
case .associatedValueEnum(let name):
36113649
return "\(name)Tag"
36123650
case .swiftStruct(let name):
3613-
return name.components(separatedBy: ".").last ?? name
3651+
return name
36143652
case .namespaceEnum(let name):
36153653
return name
36163654
case .swiftProtocol(let name):

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ struct IntrinsicJSFragment: Sendable {
944944
fullName: String,
945945
kind: JSOptionalKind
946946
) -> IntrinsicJSFragment {
947-
let base = fullName.components(separatedBy: ".").last ?? fullName
947+
let base = fullName.replacingOccurrences(of: ".", with: "_")
948948
let absenceLiteral = kind.absenceLiteral
949949
return IntrinsicJSFragment(
950950
parameters: [],
@@ -1300,7 +1300,7 @@ struct IntrinsicJSFragment: Sendable {
13001300
let base = fullName.components(separatedBy: ".").last ?? fullName
13011301
return .associatedEnumLowerParameter(enumBase: base)
13021302
case .swiftStruct(let fullName):
1303-
let base = fullName.components(separatedBy: ".").last ?? fullName
1303+
let base = fullName.replacingOccurrences(of: ".", with: "_")
13041304
return swiftStructLowerParameter(structBase: base)
13051305
case .closure:
13061306
return IntrinsicJSFragment(
@@ -1360,7 +1360,7 @@ struct IntrinsicJSFragment: Sendable {
13601360
let base = fullName.components(separatedBy: ".").last ?? fullName
13611361
return .associatedEnumLiftReturn(enumBase: base)
13621362
case .swiftStruct(let fullName):
1363-
let base = fullName.components(separatedBy: ".").last ?? fullName
1363+
let base = fullName.replacingOccurrences(of: ".", with: "_")
13641364
return swiftStructLiftReturn(structBase: base)
13651365
case .closure:
13661366
return IntrinsicJSFragment(
@@ -1446,7 +1446,7 @@ struct IntrinsicJSFragment: Sendable {
14461446
case .importTS:
14471447
return .jsObjectLiftRetainedObjectId
14481448
case .exportSwift:
1449-
let base = fullName.components(separatedBy: ".").last ?? fullName
1449+
let base = fullName.replacingOccurrences(of: ".", with: "_")
14501450
return IntrinsicJSFragment(
14511451
parameters: [],
14521452
printCode: { arguments, context in
@@ -1805,7 +1805,7 @@ struct IntrinsicJSFragment: Sendable {
18051805
}
18061806

18071807
static func swiftStructLowerReturn(fullName: String) -> IntrinsicJSFragment {
1808-
swiftStructLower(structBase: fullName.components(separatedBy: ".").last ?? fullName)
1808+
swiftStructLower(structBase: fullName.replacingOccurrences(of: ".", with: "_"))
18091809
}
18101810

18111811
static func swiftStructLowerParameter(structBase: String) -> IntrinsicJSFragment {
@@ -2008,7 +2008,7 @@ struct IntrinsicJSFragment: Sendable {
20082008
}
20092009
)
20102010
case .swiftStruct(let fullName):
2011-
let structBase = fullName.components(separatedBy: ".").last ?? fullName
2011+
let structBase = fullName.replacingOccurrences(of: ".", with: "_")
20122012
return IntrinsicJSFragment(
20132013
parameters: [],
20142014
printCode: { arguments, context in
@@ -2130,7 +2130,7 @@ struct IntrinsicJSFragment: Sendable {
21302130
}
21312131
)
21322132
case .swiftStruct(let fullName):
2133-
let structBase = fullName.components(separatedBy: ".").last ?? fullName
2133+
let structBase = fullName.replacingOccurrences(of: ".", with: "_")
21342134
return IntrinsicJSFragment(
21352135
parameters: ["value"],
21362136
printCode: { arguments, context in
@@ -2426,7 +2426,7 @@ struct IntrinsicJSFragment: Sendable {
24262426
)
24272427
try printer.indent {
24282428
printer.write(
2429-
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(this);"
2429+
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lower(this);"
24302430
)
24312431

24322432
var paramForwardings: [String] = []
@@ -2502,7 +2502,7 @@ struct IntrinsicJSFragment: Sendable {
25022502
let printer = context.printer
25032503
let value = arguments[0]
25042504
printer.write(
2505-
"\(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));"
2505+
"\(JSGlueVariableScope.reservedStructHelpers).\(nestedName.replacingOccurrences(of: ".", with: "_")).lower(\(value));"
25062506
)
25072507
return []
25082508
}
@@ -2540,7 +2540,7 @@ struct IntrinsicJSFragment: Sendable {
25402540
let (scope, printer) = (context.scope, context.printer)
25412541
let structVar = scope.variable("struct")
25422542
printer.write(
2543-
"const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lift();"
2543+
"const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName.replacingOccurrences(of: ".", with: "_")).lift();"
25442544
)
25452545
return [structVar]
25462546
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/NestedType.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@
88
var score: Double
99
}
1010
}
11+
12+
@JS class Player {
13+
@JS func getTag() -> String {
14+
return "player"
15+
}
16+
17+
@JS struct Stats {
18+
var level: Int
19+
var rating: String
20+
}
21+
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,32 @@
2626

2727
],
2828
"swiftCallName" : "User"
29+
},
30+
{
31+
"methods" : [
32+
{
33+
"abiName" : "bjs_Player_getTag",
34+
"effects" : {
35+
"isAsync" : false,
36+
"isStatic" : false,
37+
"isThrows" : false
38+
},
39+
"name" : "getTag",
40+
"parameters" : [
41+
42+
],
43+
"returnType" : {
44+
"string" : {
45+
46+
}
47+
}
48+
}
49+
],
50+
"name" : "Player",
51+
"properties" : [
52+
53+
],
54+
"swiftCallName" : "Player"
2955
}
3056
],
3157
"enums" : [
@@ -79,6 +105,47 @@
79105
}
80106
],
81107
"swiftCallName" : "User.Stats"
108+
},
109+
{
110+
"methods" : [
111+
112+
],
113+
"name" : "Stats",
114+
"namespace" : [
115+
"Player"
116+
],
117+
"properties" : [
118+
{
119+
"isReadonly" : true,
120+
"isStatic" : false,
121+
"name" : "level",
122+
"namespace" : [
123+
"Player"
124+
],
125+
"type" : {
126+
"integer" : {
127+
"_0" : {
128+
"isSigned" : true,
129+
"width" : "word"
130+
}
131+
}
132+
}
133+
},
134+
{
135+
"isReadonly" : true,
136+
"isStatic" : false,
137+
"name" : "rating",
138+
"namespace" : [
139+
"Player"
140+
],
141+
"type" : {
142+
"string" : {
143+
144+
}
145+
}
146+
}
147+
],
148+
"swiftCallName" : "Player.Stats"
82149
}
83150
]
84151
},

0 commit comments

Comments
 (0)