@@ -29,38 +29,207 @@ package enum SwiftAPIKind: Equatable {
2929
3030/// Describes a Swift nominal type (e.g., a class, struct, enum) that has been
3131/// imported and is being translated into Java.
32+ ///
33+ /// When `base` is non-nil, this is a specialization of a generic type
34+ /// (e.g. `FishBox` specializing `Box<Element>` with `Element` = `Fish`).
35+ /// The specialization delegates its member collections to the base type
36+ /// so that extensions discovered later are visible through all specializations.
3237package final class ImportedNominalType : ImportedDecl {
3338 let swiftNominal : SwiftNominalTypeDeclaration
3439
40+ /// If this type is a specialization (FishTank), then this points at the Tank base type of the specialization.
41+ /// His allows simplified
42+ package let specializationBaseType : ImportedNominalType ?
43+
3544 // The short path from module root to the file in which this nominal was originally declared.
3645 // E.g. for `Sources/Example/My/Types.swift` it would be `My/Types.swift`.
3746 package var sourceFilePath : String {
3847 self . swiftNominal. sourceFilePath
3948 }
4049
41- package var initializers : [ ImportedFunc ] = [ ]
42- package var methods : [ ImportedFunc ] = [ ]
43- package var variables : [ ImportedFunc ] = [ ]
44- package var cases : [ ImportedEnumCase ] = [ ]
45- var inheritedTypes : [ SwiftType ]
46- package var parent : SwiftNominalTypeDeclaration ?
50+ // Backing storage for member collections
51+ private var _initializers : [ ImportedFunc ] = [ ]
52+ private var _methods : [ ImportedFunc ] = [ ]
53+ private var _variables : [ ImportedFunc ] = [ ]
54+ private var _cases : [ ImportedEnumCase ] = [ ]
55+ private var _inheritedTypes : [ SwiftType ]
56+ private var _parent : SwiftNominalTypeDeclaration ?
57+
58+ // Additional members from constrained extensions that only apply to this specialization
59+ package var constrainedInitializers : [ ImportedFunc ] = [ ]
60+ package var constrainedMethods : [ ImportedFunc ] = [ ]
61+ package var constrainedVariables : [ ImportedFunc ] = [ ]
62+
63+ package var initializers : [ ImportedFunc ] {
64+ get {
65+ if let specializationBaseType { specializationBaseType. initializers + constrainedInitializers } else { _initializers }
66+ }
67+ set {
68+ if let specializationBaseType {
69+ let baseSet = Set ( specializationBaseType. initializers. map { ObjectIdentifier ( $0) } )
70+ constrainedInitializers = newValue. filter { !baseSet. contains ( ObjectIdentifier ( $0) ) }
71+ } else {
72+ _initializers = newValue
73+ }
74+ }
75+ }
76+ package var methods : [ ImportedFunc ] {
77+ get {
78+ if let specializationBaseType { specializationBaseType. methods + constrainedMethods } else { _methods }
79+ }
80+ set {
81+ if let specializationBaseType {
82+ let baseSet = Set ( specializationBaseType. methods. map { ObjectIdentifier ( $0) } )
83+ constrainedMethods = newValue. filter { !baseSet. contains ( ObjectIdentifier ( $0) ) }
84+ } else {
85+ _methods = newValue
86+ }
87+ }
88+ }
89+ package var variables : [ ImportedFunc ] {
90+ get {
91+ if let specializationBaseType { specializationBaseType. variables + constrainedVariables } else { _variables }
92+ }
93+ set {
94+ if let specializationBaseType {
95+ let baseSet = Set ( specializationBaseType. variables. map { ObjectIdentifier ( $0) } )
96+ constrainedVariables = newValue. filter { !baseSet. contains ( ObjectIdentifier ( $0) ) }
97+ } else {
98+ _variables = newValue
99+ }
100+ }
101+ }
102+ package var cases : [ ImportedEnumCase ] {
103+ get {
104+ if let specializationBaseType { specializationBaseType. cases } else { _cases }
105+ }
106+ set {
107+ if let specializationBaseType { specializationBaseType. cases = newValue } else { _cases = newValue }
108+ }
109+ }
110+ var inheritedTypes : [ SwiftType ] {
111+ get {
112+ if let specializationBaseType { specializationBaseType. inheritedTypes } else { _inheritedTypes }
113+ }
114+ set {
115+ if let specializationBaseType { specializationBaseType. inheritedTypes = newValue } else { _inheritedTypes = newValue }
116+ }
117+ }
118+ package var parent : SwiftNominalTypeDeclaration ? {
119+ get {
120+ if let specializationBaseType { specializationBaseType. parent } else { _parent }
121+ }
122+ set {
123+ if let specializationBaseType { specializationBaseType. parent = newValue } else { _parent = newValue }
124+ }
125+ }
126+
127+ /// The Swift base type name, e.g. "Box" — always the unparameterized name
128+ package var baseTypeName : String { swiftNominal. qualifiedName }
129+
130+ /// The specialized/Java-facing name, e.g. "FishBox" — nil for base types
131+ package private( set) var specializedTypeName : String ?
132+
133+ /// Whether this type is a specialization of a generic type
134+ package var isSpecialization : Bool { specializationBaseType != nil }
135+
136+ /// Generic parameter names (e.g. ["Element"] for Box<Element>). Empty for non-generic types
137+ package var genericParameterNames : [ String ] {
138+ swiftNominal. genericParameters. map ( \. name)
139+ }
140+
141+ /// Maps generic parameter -> concrete type argument. Empty for unspecialized types
142+ /// e.g. {"Element": "Fish"} for FishBox
143+ package var genericArguments : [ String : String ] = [ : ]
144+
145+ /// True when all generic parameters have corresponding arguments
146+ package var isFullySpecialized : Bool {
147+ !genericParameterNames. isEmpty && genericParameterNames. allSatisfy { genericArguments. keys. contains ( $0) }
148+ }
47149
48150 init ( swiftNominal: SwiftNominalTypeDeclaration , lookupContext: SwiftTypeLookupContext ) throws {
49151 self . swiftNominal = swiftNominal
50- self . inheritedTypes =
152+ self . specializationBaseType = nil
153+ self . _inheritedTypes =
51154 swiftNominal. inheritanceTypes? . compactMap {
52155 try ? SwiftType ( $0. type, lookupContext: lookupContext)
53156 } ?? [ ]
54- self . parent = swiftNominal. parent
157+ self . _parent = swiftNominal. parent
158+ }
159+
160+ /// Init for creating a specialization
161+ private init ( base: ImportedNominalType , specializedTypeName: String , genericArguments: [ String : String ] ) {
162+ self . swiftNominal = base. swiftNominal
163+ self . specializationBaseType = base
164+ self . specializedTypeName = specializedTypeName
165+ self . genericArguments = genericArguments
166+ self . _inheritedTypes = [ ]
55167 }
56168
57169 var swiftType : SwiftType {
58170 . nominal( . init( nominalTypeDecl: swiftNominal) )
59171 }
60172
173+ /// The effective Java-facing name — "FishBox" for specialized, "Box" for base
174+ var effectiveJavaName : String {
175+ specializedTypeName ?? swiftNominal. qualifiedName
176+ }
177+
178+ /// The simple Java class name (no qualification) for file naming purposes
179+ var effectiveJavaSimpleName : String {
180+ specializedTypeName ?? swiftNominal. name
181+ }
182+
183+ /// The Swift type for thunk generation — "Box<Fish>" for specialized, "Box" for base
184+ /// Computed from baseTypeName + genericArguments
185+ var effectiveSwiftTypeName : String {
186+ guard !genericArguments. isEmpty else { return baseTypeName }
187+ let orderedArgs = genericParameterNames. compactMap { genericArguments [ $0] }
188+ guard !orderedArgs. isEmpty else { return baseTypeName }
189+ return " \( baseTypeName) < \( orderedArgs. joined ( separator: " , " ) ) > "
190+ }
191+
61192 var qualifiedName : String {
62193 self . swiftNominal. qualifiedName
63194 }
195+
196+ /// The Java generic clause, e.g. "<Element>" for generic base types, "" for specialized or non-generic
197+ var javaGenericClause : String {
198+ if isSpecialization {
199+ " "
200+ } else if genericParameterNames. isEmpty {
201+ " "
202+ } else {
203+ " < \( genericParameterNames. joined ( separator: " , " ) ) > "
204+ }
205+ }
206+
207+ /// Create a specialized version of this generic type
208+ package func specialize(
209+ as specializedName: String ,
210+ with substitutions: [ String : String ] ,
211+ ) throws -> ImportedNominalType {
212+ guard !genericParameterNames. isEmpty else {
213+ throw SpecializationError (
214+ message: " Unable to specialize non-generic type ' \( baseTypeName) ' as ' \( specializedName) ' "
215+ )
216+ }
217+ let missingParams = genericParameterNames. filter { substitutions [ $0] == nil }
218+ guard missingParams. isEmpty else {
219+ throw SpecializationError (
220+ message: " Missing type arguments for: \( missingParams) when specializing \( baseTypeName) as \( specializedName) "
221+ )
222+ }
223+ return ImportedNominalType (
224+ base: self ,
225+ specializedTypeName: specializedName,
226+ genericArguments: substitutions,
227+ )
228+ }
229+ }
230+
231+ struct SpecializationError : Error {
232+ let message : String
64233}
65234
66235public final class ImportedEnumCase : ImportedDecl , CustomStringConvertible {
@@ -82,7 +251,7 @@ public final class ImportedEnumCase: ImportedDecl, CustomStringConvertible {
82251 parameters: [ SwiftEnumCaseParameter ] ,
83252 swiftDecl: any DeclSyntaxProtocol ,
84253 enumType: SwiftNominalType ,
85- caseFunction: ImportedFunc
254+ caseFunction: ImportedFunc ,
86255 ) {
87256 self . name = name
88257 self . parameters = parameters
@@ -191,7 +360,7 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible {
191360 swiftDecl: any DeclSyntaxProtocol ,
192361 name: String ,
193362 apiKind: SwiftAPIKind ,
194- functionSignature: SwiftFunctionSignature
363+ functionSignature: SwiftFunctionSignature ,
195364 ) {
196365 self . module = module
197366 self . name = name
0 commit comments