From 25f0e75fd332add700cc31d544fab927f4e000a4 Mon Sep 17 00:00:00 2001 From: Tristan Labelle Date: Tue, 17 Dec 2024 08:10:27 -0500 Subject: [PATCH] Refactor SwiftType to support arbitrary chaining --- .../CodeWriters/Swift/SwiftType+write.swift | 72 ++++---- .../Sources/CodeWriters/Swift/SwiftType.swift | 167 ++++++++---------- .../ProjectionModel/Projection+abi.swift | 4 +- .../Projection+conversion.swift | 4 +- .../ProjectionModel/Projection+params.swift | 2 +- .../ProjectionModel/Projection+types.swift | 47 +++-- .../ProjectionModel/SupportModules.swift | 90 +++++----- .../ProjectionModel/TypeProjection.swift | 2 +- .../SwiftWinRT/Writing/ABIBinding.swift | 14 +- .../SwiftWinRT/Writing/COMImportClass.swift | 4 +- .../Writing/COMInteropExtension.swift | 9 +- .../SwiftWinRT/Writing/ClassDefinition.swift | 8 +- .../SwiftWinRT/Writing/EnumDefinition.swift | 8 +- .../Writing/InterfaceDefinition.swift | 14 +- .../SwiftWinRT/Writing/NamespaceModules.swift | 9 +- .../Writing/NonthrowingProperties.swift | 2 +- .../Writing/SecondaryInterfaces.swift | 2 +- .../SwiftWinRT/Writing/StructDefinition.swift | 6 +- 18 files changed, 224 insertions(+), 240 deletions(-) diff --git a/Generator/Sources/CodeWriters/Swift/SwiftType+write.swift b/Generator/Sources/CodeWriters/Swift/SwiftType+write.swift index fcf3ed8c..cc47d524 100644 --- a/Generator/Sources/CodeWriters/Swift/SwiftType+write.swift +++ b/Generator/Sources/CodeWriters/Swift/SwiftType+write.swift @@ -5,39 +5,52 @@ extension SwiftType: CustomStringConvertible, TextOutputStreamable { return output } + private func writeNamed(_ identifier: SwiftIdentifier, genericArgs: [SwiftType], to output: inout some TextOutputStream) { + identifier.write(to: &output) + if !genericArgs.isEmpty { + output.write("<") + for (index, arg) in genericArgs.enumerated() { + if index > 0 { output.write(", ") } + arg.write(to: &output) + } + output.write(">") + } + } + + private func writeParenthesizingProtocolModifiers(_ type: SwiftType, to output: inout some TextOutputStream) { + switch type { + case let .existential(`protocol`), let .opaque(`protocol`): + output.write("(") + `protocol`.write(to: &output) + output.write(")") + default: + type.write(to: &output) + } + } + public func write(to output: inout some TextOutputStream) { switch self { - case let .chain(chain): - if chain.protocolModifier == .any { - output.write("any ") - } - else if chain.protocolModifier == .some { - output.write("some ") - } + case .self: output.write("Self") + case .any: output.write("Any") - for (index, component) in chain.components.enumerated() { - if index > 0 { output.write(".") } - component.identifier.write(to: &output) - guard !component.genericArgs.isEmpty else { continue } - output.write("<") - for (index, arg) in component.genericArgs.enumerated() { - if index > 0 { output.write(", ") } - arg.write(to: &output) - } - output.write(">") - } + case let .named(identifier, genericArgs): + writeNamed(identifier, genericArgs: genericArgs, to: &output) + + case let .member(of, identifier, genericArgs): + writeParenthesizingProtocolModifiers(of, to: &output) + output.write(".") + writeNamed(identifier, genericArgs: genericArgs, to: &output) + + case let .opaque(`protocol`): + output.write("some ") + `protocol`.write(to: &output) + + case let .existential(`protocol`): + output.write("any ") + `protocol`.write(to: &output) case let .`optional`(wrapped, forceUnwrap): - let parenthesized: Bool - if case let .chain(chain) = wrapped, chain.protocolModifier != nil { - output.write("(") - parenthesized = true - } - else { - parenthesized = false - } - wrapped.write(to: &output) - if parenthesized { output.write(")") } + writeParenthesizingProtocolModifiers(wrapped, to: &output) output.write(forceUnwrap ? "!" : "?") case let .tuple(elements): @@ -70,9 +83,6 @@ extension SwiftType: CustomStringConvertible, TextOutputStreamable { if `throws` { output.write(" throws") } output.write(" -> ") returnType.write(to: &output) - - case .self: output.write("Self") - case .any: output.write("Any") } } } diff --git a/Generator/Sources/CodeWriters/Swift/SwiftType.swift b/Generator/Sources/CodeWriters/Swift/SwiftType.swift index 6f7975fd..2f22f0e4 100644 --- a/Generator/Sources/CodeWriters/Swift/SwiftType.swift +++ b/Generator/Sources/CodeWriters/Swift/SwiftType.swift @@ -1,125 +1,106 @@ -// See https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types +// Loosely based on https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types +// However that grammar has a bug: it cannot represent "[Int].Element" public enum SwiftType { - /// An identifier chain, such as "Foo.Bar" or "any Foo.Bar". - case chain(Chain) - indirect case `optional`(wrapped: SwiftType, implicitUnwrap: Bool = false) - indirect case tuple(elements: [SwiftType]) - indirect case array(element: SwiftType) - indirect case dictionary(key: SwiftType, value: SwiftType) - indirect case function(params: [SwiftType], throws: Bool = false, returnType: SwiftType) + // Self case `self` + // Any case any - public enum ProtocolModifier { - case any // existential - case some // opaque - } + // Foo + case named(SwiftIdentifier, genericArgs: [SwiftType] = []) - public struct Chain { - public let protocolModifier: ProtocolModifier? - public let components: [ChainComponent] + // X.Foo + indirect case member(of: SwiftType, SwiftIdentifier, genericArgs: [SwiftType] = []) - public init(protocolModifier: ProtocolModifier? = nil, _ components: [ChainComponent]) { - precondition(!components.isEmpty) - self.protocolModifier = protocolModifier - self.components = components - } - - public func appending(_ component: ChainComponent) -> Chain { - Chain(protocolModifier: protocolModifier, components + [component]) - } + // some X + indirect case opaque(protocol: SwiftType) + // any X + indirect case existential(protocol: SwiftType) - public func appending(_ identifier: String, genericArgs: [SwiftType] = []) -> Chain { - appending(ChainComponent(identifier, genericArgs: genericArgs)) - } - } - - public struct ChainComponent { - public let identifier: SwiftIdentifier - public let genericArgs: [SwiftType] - - public init(_ identifier: String, genericArgs: [SwiftType] = []) { - self.identifier = SwiftIdentifier(identifier) - self.genericArgs = genericArgs - } - } + // X? + indirect case `optional`(wrapped: SwiftType, implicitUnwrap: Bool = false) + // (X, Y) + indirect case tuple(elements: [SwiftType]) + // [X] + indirect case array(element: SwiftType) + // [X: Y] + indirect case dictionary(key: SwiftType, value: SwiftType) + // (X, Y) throws -> Z + indirect case function(params: [SwiftType], throws: Bool = false, returnType: SwiftType) } extension SwiftType { - public static let void: SwiftType = .chain("Swift", "Void") - public static let anyObject: SwiftType = .chain("Swift", "AnyObject") - public static let never: SwiftType = .chain("Swift", "Never") - public static let bool: SwiftType = .chain("Swift", "Bool") - public static let float: SwiftType = .chain("Swift", "Float") - public static let double: SwiftType = .chain("Swift", "Double") - public static let string: SwiftType = .chain("Swift", "String") - public static let int: SwiftType = .chain("Swift", "Int") - public static let uint: SwiftType = .chain("Swift", "UInt") - - public static func int(bits: Int, signed: Bool = true) -> SwiftType { - switch (bits, signed) { - case (8, true): return .chain("Swift", "Int8") - case (8, false): return .chain("Swift", "UInt8") - case (16, true): return .chain("Swift", "Int16") - case (16, false): return .chain("Swift", "UInt16") - case (32, true): return .chain("Swift", "Int32") - case (32, false): return .chain("Swift", "UInt32") - case (64, true): return .chain("Swift", "Int64") - case (64, false): return .chain("Swift", "UInt64") - default: preconditionFailure("bits should be one of 8, 16, 32 or 64") - } + public static func named(_ name: String, genericArgs: [SwiftType] = []) -> Self { + .named(SwiftIdentifier(name), genericArgs: genericArgs) } - public static func uint(bits: Int) -> SwiftType { int(bits: bits, signed: false) } - - public static func identifier( - protocolModifier: SwiftType.ProtocolModifier? = nil, - name: String, - genericArgs: [SwiftType] = []) -> SwiftType { + public func metatype() -> Self { .member(of: self, "Type") } - .chain(Chain(protocolModifier: protocolModifier, [ ChainComponent(name, genericArgs: genericArgs) ])) + public func member(_ name: String, genericArgs: [SwiftType] = []) -> Self { + member(SwiftIdentifier(name), genericArgs: genericArgs) } - public static func identifier(_ name: String, genericArgs: [SwiftType] = []) -> SwiftType { - identifier(name: name, genericArgs: genericArgs) + public func member(_ name: SwiftIdentifier, genericArgs: [SwiftType] = []) -> Self { + .member(of: self, name, genericArgs: genericArgs) } - public static func chain( - protocolModifier: SwiftType.ProtocolModifier? = nil, - _ components: [ChainComponent]) -> SwiftType { + public func opaque() -> Self { .opaque(protocol: self) } + public func existential() -> Self { .existential(protocol: self) } - .chain(Chain(protocolModifier: protocolModifier, components)) + public func optional(implicitUnwrap: Bool = false) -> Self { + .optional(wrapped: self, implicitUnwrap: implicitUnwrap) } - public static func chain( - protocolModifier: SwiftType.ProtocolModifier? = nil, - _ components: ChainComponent...) -> SwiftType { - - .chain(protocolModifier: protocolModifier, components) + public func unwrapOptional() -> SwiftType { + switch self { + case let .optional(wrapped, _): return wrapped + default: return self + } } +} - public static func chain( - protocolModifier: SwiftType.ProtocolModifier? = nil, - _ identifiers: [String]) -> SwiftType { +extension SwiftType { + private static let swiftModule: Self = .named("Swift") - .chain(Chain(protocolModifier: protocolModifier, identifiers.map { ChainComponent($0) })) + public static func swift(_ identifier: SwiftIdentifier, genericArgs: [SwiftType] = []) -> Self { + swiftModule.member(identifier, genericArgs: genericArgs) } - public static func chain( - protocolModifier: SwiftType.ProtocolModifier? = nil, - _ identifiers: String...) -> SwiftType { - - .chain(protocolModifier: protocolModifier, identifiers) + public static func swift(_ identifier: String, genericArgs: [SwiftType] = []) -> Self { + swiftModule.member(SwiftIdentifier(identifier), genericArgs: genericArgs) } - public func unwrapOptional() -> SwiftType { - switch self { - case let .optional(wrapped, _): return wrapped - default: return self + public static let void: Self = swift("Void") + public static let anyObject: Self = swift("AnyObject") + public static let never: Self = swift("Never") + public static let bool: Self = swift("Bool") + public static let float: Self = swift("Float") + public static let double: Self = swift("Double") + public static let string: Self = swift("String") + public static let int: Self = swift("Int") + public static let uint: Self = swift("UInt") + + public static func int(bits: Int, signed: Bool = true) -> Self { + switch (bits, signed) { + case (8, true): return swift("Int8") + case (8, false): return swift("UInt8") + case (16, true): return swift("Int16") + case (16, false): return swift("UInt16") + case (32, true): return swift("Int32") + case (32, false): return swift("UInt32") + case (64, true): return swift("Int64") + case (64, false): return swift("UInt64") + default: preconditionFailure("bits should be one of 8, 16, 32 or 64") } } - public static func unsafeMutablePointer(to pointee: SwiftType) -> SwiftType { - .chain(.init("Swift"), .init("UnsafeMutablePointer", genericArgs: [pointee])) + public static func uint(bits: Int) -> Self { int(bits: bits, signed: false) } + + public static func unsafePointer(pointee: SwiftType) -> SwiftType { + swift("UnsafePointer", genericArgs: [pointee]) + } + + public static func unsafeMutablePointer(pointee: SwiftType) -> SwiftType { + swift("UnsafeMutablePointer", genericArgs: [pointee]) } } diff --git a/Generator/Sources/ProjectionModel/Projection+abi.swift b/Generator/Sources/ProjectionModel/Projection+abi.swift index 3102d9c2..4586b512 100644 --- a/Generator/Sources/ProjectionModel/Projection+abi.swift +++ b/Generator/Sources/ProjectionModel/Projection+abi.swift @@ -13,11 +13,11 @@ extension Projection { return try toABIType(defaultInterface.asBoundType) } - return .identifier(try CAbi.mangleName(type: type)) + return .named(try CAbi.mangleName(type: type)) } public func toABIVirtualTableType(_ type: BoundType) throws -> SwiftType { precondition(type.definition is InterfaceDefinition || type.definition is DelegateDefinition) - return .identifier(try CAbi.mangleName(type: type) + CAbi.virtualTableSuffix) + return .named(try CAbi.mangleName(type: type) + CAbi.virtualTableSuffix) } } \ No newline at end of file diff --git a/Generator/Sources/ProjectionModel/Projection+conversion.swift b/Generator/Sources/ProjectionModel/Projection+conversion.swift index ede4d120..de6f8520 100644 --- a/Generator/Sources/ProjectionModel/Projection+conversion.swift +++ b/Generator/Sources/ProjectionModel/Projection+conversion.swift @@ -21,7 +21,7 @@ extension Projection { public func toBaseProtocol(_ interface: InterfaceDefinition) throws -> SwiftType { // Protocols have no generic arguments in base type lists - .identifier(name: try toProtocolName(interface)) + .named(try toProtocolName(interface)) } public func toBaseType(_ type: BoundType?) throws -> SwiftType? { @@ -34,7 +34,7 @@ extension Projection { return try toBaseProtocol(interfaceDefinition) } else { - return .identifier(name: try toTypeName(type.definition)) + return .named(try toTypeName(type.definition)) } } diff --git a/Generator/Sources/ProjectionModel/Projection+params.swift b/Generator/Sources/ProjectionModel/Projection+params.swift index ef507be5..cfd30c90 100644 --- a/Generator/Sources/ProjectionModel/Projection+params.swift +++ b/Generator/Sources/ProjectionModel/Projection+params.swift @@ -67,7 +67,7 @@ extension Projection { returnBinding = ParamProjection( name: "_result", typeProjection: TypeProjection( - abiType: .optional(wrapped: .unsafeMutablePointer(to: abiType)), + abiType: .unsafeMutablePointer(pointee: abiType).optional(), abiDefaultValue: .`nil`, swiftType: SupportModules.COM.comReference(to: abiType), swiftDefaultValue: .`nil`, // No projection needed diff --git a/Generator/Sources/ProjectionModel/Projection+types.swift b/Generator/Sources/ProjectionModel/Projection+types.swift index 52aa4cdd..6616d453 100644 --- a/Generator/Sources/ProjectionModel/Projection+types.swift +++ b/Generator/Sources/ProjectionModel/Projection+types.swift @@ -8,7 +8,7 @@ extension Projection { case let .bound(type): return try toType(type) case let .genericParam(param): - return .identifier(param.name) + return .named(param.name) case let .array(of: element): return .array(element: try toType(element)) default: @@ -21,10 +21,10 @@ extension Projection { return specialTypeBinding.swiftType } - let swiftObjectType = SwiftType.identifier( - name: try toTypeName(boundType.definition), + let swiftObjectType: SwiftType = .named( + try toTypeName(boundType.definition), genericArgs: try boundType.genericArgs.map { try toType($0) }) - return boundType.definition.isReferenceType && nullable ? .optional(wrapped: swiftObjectType) : swiftObjectType + return boundType.definition.isReferenceType && nullable ? swiftObjectType.optional() : swiftObjectType } public func isPODBinding(_ typeDefinition: TypeDefinition) throws -> Bool { @@ -98,26 +98,24 @@ extension Projection { guard let defaultInterface = try DefaultAttribute.getDefaultInterface(classDefinition) else { throw WinMDError.missingAttribute } - abiType = SwiftType.identifier(name: try CAbi.mangleName(type: defaultInterface.asBoundType)) + abiType = .named(try CAbi.mangleName(type: defaultInterface.asBoundType)) } else { - abiType = SwiftType.identifier(name: try CAbi.mangleName(type: type)) + abiType = .named(try CAbi.mangleName(type: type)) } if type.definition.isReferenceType { - abiType = .optional(wrapped: .unsafeMutablePointer(to: abiType)) + abiType = .unsafeMutablePointer(pointee: abiType).optional() } let bindingType: SwiftType = try { let bindingTypeName = try toBindingTypeName(type.definition) if type.genericArgs.isEmpty { - return .identifier(bindingTypeName) + return .named(bindingTypeName) } else { - return .chain([ - .init(bindingTypeName), - .init(try Projection.toBindingInstantiationTypeName(genericArgs: type.genericArgs)) - ]) + return .named(bindingTypeName) + .member(try Projection.toBindingInstantiationTypeName(genericArgs: type.genericArgs)) } }() @@ -151,9 +149,9 @@ extension Projection { if type.definition.name == "Object" { return .init( - abiType: .optional(wrapped: SupportModules.WinRT.iinspectablePointer), + abiType: SupportModules.WinRT.iinspectablePointer.optional(), abiDefaultValue: .nil, - swiftType: .optional(wrapped: SupportModules.WinRT.iinspectable), + swiftType: SupportModules.WinRT.iinspectable.optional(), swiftDefaultValue: .nil, bindingType: SupportModules.WinRT.iinspectableBinding, kind: .allocating) @@ -163,9 +161,10 @@ extension Projection { switch primitiveType { // Identity projections case .boolean, .integer(_), .float(_): - let swiftType = primitiveType == .boolean ? SwiftType.bool - : primitiveType == .float(double: false) ? SwiftType.float - : SwiftType.chain("Swift", primitiveType.name) + // These have the same name between .NET and Swift, except for Bool and Float + let swiftType: SwiftType = primitiveType == .boolean ? .bool + : primitiveType == .float(double: false) ? .float + : .swift(primitiveType.name) return TypeProjection( abiType: swiftType, abiDefaultValue: primitiveType == .boolean ? .`false` : .zero, @@ -175,7 +174,7 @@ extension Projection { kind: .identity) case .char16: return TypeProjection( - abiType: .chain("Swift", "UInt16"), + abiType: .swift("UInt16"), abiDefaultValue: .zero, swiftType: SupportModules.WinRT.char16, swiftDefaultValue: ".init(0)", @@ -183,7 +182,7 @@ extension Projection { kind: .pod) case .guid: return TypeProjection( - abiType: .identifier(CAbi.guidName), + abiType: .named(CAbi.guidName), abiDefaultValue: .defaultInitializer, swiftType: SupportModules.COM.guid, swiftDefaultValue: .defaultInitializer, @@ -191,7 +190,7 @@ extension Projection { kind: .pod) case .string: return .init( - abiType: .optional(wrapped: .identifier(CAbi.hstringName)), + abiType: .named(CAbi.hstringName).optional(), abiDefaultValue: .nil, swiftType: .string, swiftDefaultValue: .emptyString, @@ -209,7 +208,7 @@ extension Projection { case "EventRegistrationToken": return TypeProjection( - abiType: .identifier(CAbi.eventRegistrationTokenName), + abiType: .named(CAbi.eventRegistrationTokenName), abiDefaultValue: .defaultInitializer, swiftType: SupportModules.WinRT.eventRegistrationToken, swiftDefaultValue: .defaultInitializer, @@ -218,7 +217,7 @@ extension Projection { case "HResult": return TypeProjection( - abiType: .identifier(CAbi.hresultName), + abiType: .named(CAbi.hresultName), abiDefaultValue: .zero, swiftType: SupportModules.COM.hresult, swiftDefaultValue: .defaultInitializer, @@ -245,9 +244,9 @@ extension Projection { } return TypeProjection( - abiType: .optional(wrapped: .unsafeMutablePointer(to: .identifier(CAbi.ireferenceName))), + abiType: .unsafeMutablePointer(pointee: .named(CAbi.ireferenceName)).optional(), abiDefaultValue: .nil, - swiftType: .optional(wrapped: typeProjection.swiftType), + swiftType: typeProjection.swiftType.optional(), swiftDefaultValue: .nil, bindingType: bindingType, kind: .allocating) diff --git a/Generator/Sources/ProjectionModel/SupportModules.swift b/Generator/Sources/ProjectionModel/SupportModules.swift index 5c201860..027c01b6 100644 --- a/Generator/Sources/ProjectionModel/SupportModules.swift +++ b/Generator/Sources/ProjectionModel/SupportModules.swift @@ -9,97 +9,101 @@ public enum SupportModules { extension SupportModules.COM { public static var moduleName: String { "COM" } + public static let moduleType: SwiftType = .named(moduleName) + public static var abiModuleName: String { "COM_ABI" } - public static var guid: SwiftType { .chain(moduleName, "GUID") } + public static var guid: SwiftType { moduleType.member("GUID") } - public static var iunknownPointer: SwiftType { .chain(moduleName, "IUnknownPointer") } - public static var iunknownReference: SwiftType { .chain(moduleName, "IUnknownReference") } - public static var iunknownReference_Optional: SwiftType { .chain(moduleName, "IUnknownReference", "Optional") } - public static var comInterfaceID: SwiftType { .chain(moduleName, "COMInterfaceID") } - public static var nullResult: SwiftType { .chain(moduleName, "NullResult") } + public static var iunknownPointer: SwiftType { moduleType.member("IUnknownPointer") } + public static var iunknownReference: SwiftType { moduleType.member("IUnknownReference") } + public static var iunknownReference_Optional: SwiftType { iunknownReference.member("Optional") } + public static var comInterfaceID: SwiftType { moduleType.member("COMInterfaceID") } + public static var nullResult: SwiftType { moduleType.member("NullResult") } - public static var hresult: SwiftType { .chain(moduleName, "HResult") } + public static var hresult: SwiftType { moduleType.member("HResult") } - public static var abiBinding: SwiftType { .chain(moduleName, "ABIBinding") } - public static var abiPODBinding: SwiftType { .chain(moduleName, "PODBinding") } - public static var boolBinding: SwiftType { .chain(moduleName, "BoolBinding") } - public static var wideCharBinding: SwiftType { .chain(moduleName, "WideCharBinding") } - public static var guidBinding: SwiftType { .chain(moduleName, "GUIDBinding") } - public static var hresultBinding: SwiftType { .chain(moduleName, "HResultBinding") } + public static var abiBinding: SwiftType { moduleType.member("ABIBinding") } + public static var abiPODBinding: SwiftType { moduleType.member("PODBinding") } + public static var boolBinding: SwiftType { moduleType.member("BoolBinding") } + public static var wideCharBinding: SwiftType { moduleType.member("WideCharBinding") } + public static var guidBinding: SwiftType { moduleType.member("GUIDBinding") } + public static var hresultBinding: SwiftType { moduleType.member("HResultBinding") } - public static var comBinding: SwiftType { .chain(moduleName, "COMBinding") } - public static var comTwoWayBinding: SwiftType { .chain(moduleName, "COMTwoWayBinding") } + public static var comBinding: SwiftType { moduleType.member("COMBinding") } + public static var comTwoWayBinding: SwiftType { moduleType.member("COMTwoWayBinding") } - public static var comEmbedding: SwiftType { .chain(moduleName, "COMEmbedding") } + public static var comEmbedding: SwiftType { moduleType.member("COMEmbedding") } - public static var comReference: SwiftType { .chain(moduleName, "COMReference") } + public static var comReference: SwiftType { moduleType.member("COMReference") } public static func comReference(to type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("COMReference", genericArgs: [type]) ]) + moduleType.member("COMReference", genericArgs: [type]) } - public static var comReference_Optional: SwiftType { .chain(moduleName, "COMReference.Optional") } + public static var comReference_Optional: SwiftType { moduleType.member("COMReference.Optional") } public static func comReference_Optional(to type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("COMReference", genericArgs: [type]), .init("Optional") ]) + comReference(to: type).member("Optional") } public static var comReference_Optional_lazyInitInterop: String { "lazyInitInterop" } public static var comReference_Optional_lazyInitPointer: String { "lazyInitPointer" } - public static var comInterop: SwiftType { .chain(moduleName, "COMInterop") } + public static var comInterop: SwiftType { moduleType.member("COMInterop") } public static func comInterop(of type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("COMInterop", genericArgs: [type]) ]) + moduleType.member("COMInterop", genericArgs: [type]) } public static func comArray(of type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("COMArray", genericArgs: [type]) ]) + moduleType.member("COMArray", genericArgs: [type]) } } extension SupportModules.WinRT { public static var moduleName: String { "WindowsRuntime" } + public static let moduleType: SwiftType = .named(moduleName) + public static var abiModuleName: String { "WindowsRuntime_ABI" } - public static var char16: SwiftType { .chain(moduleName, "Char16") } + public static var char16: SwiftType { moduleType.member("Char16") } - public static var eventRegistration: SwiftType { .chain(moduleName, "EventRegistration") } - public static var eventRegistrationToken: SwiftType { .chain(moduleName, "EventRegistrationToken") } - public static var iinspectable: SwiftType { .chain(moduleName, "IInspectable") } - public static var iinspectablePointer: SwiftType { .chain(moduleName, "IInspectablePointer") } - public static var iinspectableBinding: SwiftType { .chain(moduleName, "IInspectableBinding") } + public static var eventRegistration: SwiftType { moduleType.member("EventRegistration") } + public static var eventRegistrationToken: SwiftType { moduleType.member("EventRegistrationToken") } + public static var iinspectable: SwiftType { moduleType.member("IInspectable") } + public static var iinspectablePointer: SwiftType { moduleType.member("IInspectablePointer") } + public static var iinspectableBinding: SwiftType { moduleType.member("IInspectableBinding") } - public static var openEnumBinding: SwiftType { .chain(moduleName, "OpenEnumBinding") } - public static var closedEnumBinding: SwiftType { .chain(moduleName, "ClosedEnumBinding") } - public static var structBinding: SwiftType { .chain(moduleName, "StructBinding") } - public static var interfaceBinding: SwiftType { .chain(moduleName, "InterfaceBinding") } - public static var delegateBinding: SwiftType { .chain(moduleName, "DelegateBinding") } - public static var runtimeClassBinding: SwiftType { .chain(moduleName, "RuntimeClassBinding") } - public static var composableClassBinding: SwiftType { .chain(moduleName, "ComposableClassBinding") } + public static var openEnumBinding: SwiftType { moduleType.member("OpenEnumBinding") } + public static var closedEnumBinding: SwiftType { moduleType.member("ClosedEnumBinding") } + public static var structBinding: SwiftType { moduleType.member("StructBinding") } + public static var interfaceBinding: SwiftType { moduleType.member("InterfaceBinding") } + public static var delegateBinding: SwiftType { moduleType.member("DelegateBinding") } + public static var runtimeClassBinding: SwiftType { moduleType.member("RuntimeClassBinding") } + public static var composableClassBinding: SwiftType { moduleType.member("ComposableClassBinding") } - public static var composableClass: SwiftType { .chain(moduleName, "ComposableClass") } + public static var composableClass: SwiftType { moduleType.member("ComposableClass") } public static var composableClass_supportsOverrides: String { "supportsOverrides" } public static func winRTImport(of type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("WinRTImport", genericArgs: [type]) ]) + moduleType.member("WinRTImport", genericArgs: [type]) } public static func arrayBinding(of type: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("ArrayBinding", genericArgs: [type]) ]) + moduleType.member("ArrayBinding", genericArgs: [type]) } public static func primitiveBinding(of type: WinRTPrimitiveType) -> SwiftType { - .chain([ .init(moduleName), .init(type.name + "Binding") ]) + moduleType.member(type.name + "Binding") } public static func ireferenceToOptionalBinding(of type: WinRTPrimitiveType) -> SwiftType { - .chain([ .init(moduleName), .init(type.name + "Binding"), .init("IReferenceToOptional") ]) + moduleType.member(type.name + "Binding").member("IReferenceToOptional") } public static func ireferenceToOptionalBinding(of bindingType: SwiftType) -> SwiftType { - .chain([ .init(moduleName), .init("IReferenceToOptionalBinding", genericArgs: [ bindingType ]) ]) + moduleType.member("IReferenceToOptionalBinding", genericArgs: [ bindingType ]) } - public static var iactivationFactoryBinding: SwiftType { .chain(moduleName, "IActivationFactoryBinding") } + public static var iactivationFactoryBinding: SwiftType { moduleType.member("IActivationFactoryBinding") } public static var activationFactoryResolverGlobal: String { "\(moduleName).activationFactoryResolver" } public static var swiftWrapperFactoryGlobal: String { "\(moduleName).swiftWrapperFactory" } diff --git a/Generator/Sources/ProjectionModel/TypeProjection.swift b/Generator/Sources/ProjectionModel/TypeProjection.swift index 6395a280..997aadec 100644 --- a/Generator/Sources/ProjectionModel/TypeProjection.swift +++ b/Generator/Sources/ProjectionModel/TypeProjection.swift @@ -63,7 +63,7 @@ public struct TypeProjection { abiDefaultValue: "0", swiftType: type, swiftDefaultValue: "0", - bindingType: .identifier("NumericBinding", genericArgs: [type]), + bindingType: .named("NumericBinding", genericArgs: [type]), kind: .identity) } } \ No newline at end of file diff --git a/Generator/Sources/SwiftWinRT/Writing/ABIBinding.swift b/Generator/Sources/SwiftWinRT/Writing/ABIBinding.swift index d44a1713..ff13fc41 100644 --- a/Generator/Sources/SwiftWinRT/Writing/ABIBinding.swift +++ b/Generator/Sources/SwiftWinRT/Writing/ABIBinding.swift @@ -30,7 +30,7 @@ internal func writeABIBindingConformance(_ typeDefinition: TypeDefinition, gener let enumBindingProtocol = try projection.isSwiftEnumEligible(enumDefinition) ? SupportModules.WinRT.closedEnumBinding : SupportModules.WinRT.openEnumBinding try writer.writeExtension( - type: .identifier(projection.toTypeName(enumDefinition)), + type: .named(projection.toTypeName(enumDefinition)), protocolConformances: [ enumBindingProtocol ]) { writer in // public static var typeName: String { "..." } try writeTypeNameProperty(type: enumDefinition.bindType(), to: writer) @@ -67,7 +67,7 @@ internal func writeABIBindingConformance(_ typeDefinition: TypeDefinition, gener // internal final class Boolean: WinRTBinding... {} // } try writer.writeExtension( - type: .identifier(projection.toBindingTypeName(typeDefinition))) { writer in + type: .named(projection.toBindingTypeName(typeDefinition))) { writer in try writeInterfaceOrDelegateBindingType( typeDefinition.bindType(genericArgs: genericArgs), projectionName: try Projection.toBindingInstantiationTypeName(genericArgs: genericArgs), @@ -98,7 +98,7 @@ fileprivate func writeStructBindingExtension( // extension : IReferenceableBinding[, PODBinding] try writer.writeExtension( - type: .identifier(projection.toTypeName(structDefinition)), + type: .named(projection.toTypeName(structDefinition)), protocolConformances: protocolConformances) { writer in let abiType = try projection.toABIType(structDefinition.bindType()) @@ -341,7 +341,7 @@ fileprivate func writeInterfaceOrDelegateBindingType( // public static var virtualTablePointer: UnsafeRawPointer { .init(withUnsafePointer(to: &virtualTable) { $0 }) } writer.writeComputedProperty( visibility: .public, static: true, name: "virtualTablePointer", - type: .identifier("UnsafeRawPointer")) { writer in + type: .named("UnsafeRawPointer")) { writer in writer.writeStatement(".init(withUnsafePointer(to: &virtualTable) { $0 })") } @@ -383,19 +383,19 @@ internal func writeReferenceTypeBindingConformance( try writeIReferenceIDProperties(boxableType: apiType, to: writer) } - let abiReferenceType = SwiftType.identifier("ABIReference") + let abiReferenceType: SwiftType = .named("ABIReference") try writer.writeFunc( visibility: .public, static: true, name: "_wrap", params: [ .init(label: "_", name: "reference", consuming: true, type: abiReferenceType) ], - returnType: .identifier("SwiftObject")) { writer in + returnType: .named("SwiftObject")) { writer in try wrapImpl(&writer, "reference") } if let toCOMImpl { try writer.writeFunc( visibility: .public, static: true, name: "toCOM", - params: [ .init(label: "_", name: "object", escaping: abiType.definition is DelegateDefinition, type: .identifier("SwiftObject")) ], + params: [ .init(label: "_", name: "object", escaping: abiType.definition is DelegateDefinition, type: .named("SwiftObject")) ], throws: true, returnType: abiReferenceType) { writer in try toCOMImpl(&writer, "object") } diff --git a/Generator/Sources/SwiftWinRT/Writing/COMImportClass.swift b/Generator/Sources/SwiftWinRT/Writing/COMImportClass.swift index dec3abeb..25f94a1c 100644 --- a/Generator/Sources/SwiftWinRT/Writing/COMImportClass.swift +++ b/Generator/Sources/SwiftWinRT/Writing/COMImportClass.swift @@ -17,7 +17,7 @@ internal func writeCOMImportClass( switch type.definition { case let interfaceDefinition as InterfaceDefinition: importBaseTypeName = "WinRTImport" - protocolConformances = [ .identifier(name: try projection.toProtocolName(interfaceDefinition)) ] + protocolConformances = [.named(try projection.toProtocolName(interfaceDefinition)) ] case is DelegateDefinition: importBaseTypeName = "COMImport" protocolConformances = [] @@ -27,7 +27,7 @@ internal func writeCOMImportClass( // private final class Import: WinRTImport, IFooProtocol {} try writer.writeClass( visibility: visibility, final: true, name: name, - base: .identifier(name: importBaseTypeName, genericArgs: [.identifier(name: projectionName)]), + base: .named(importBaseTypeName, genericArgs: [ .named(projectionName) ]), protocolConformances: protocolConformances) { writer throws in let interfaces = try type.definition.baseInterfaces.map { diff --git a/Generator/Sources/SwiftWinRT/Writing/COMInteropExtension.swift b/Generator/Sources/SwiftWinRT/Writing/COMInteropExtension.swift index edd99d48..8d281864 100644 --- a/Generator/Sources/SwiftWinRT/Writing/COMInteropExtension.swift +++ b/Generator/Sources/SwiftWinRT/Writing/COMInteropExtension.swift @@ -10,16 +10,9 @@ internal func writeCOMInteropExtension(abiType: BoundType, projection: Projectio let visibility: SwiftVisibility = abiType.genericArgs.isEmpty ? .public : .internal // func uuidof(_: SWRT_IFoo.Type) -> COMInterfaceID - let abiSwiftMetatype: SwiftType - if case let .chain(chain) = abiSwiftType { - abiSwiftMetatype = .chain(chain.appending("Type")) - } else { - fatalError("Can't chain .Type to \(abiSwiftType)") - } - try writer.writeFunc( visibility: visibility, name: "uuidof", - params: [ .init(name: "_", type: abiSwiftMetatype) ], + params: [ .init(name: "_", type: abiSwiftType.metatype()) ], returnType: SupportModules.COM.comInterfaceID) { writer in writer.output.writeFullLine(try toIIDExpression(WindowsMetadata.getInterfaceID(abiType))) } diff --git a/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift b/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift index c476c646..d8aa326a 100644 --- a/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift +++ b/Generator/Sources/SwiftWinRT/Writing/ClassDefinition.swift @@ -31,7 +31,7 @@ internal func writeClassDefinition(_ classDefinition: ClassDefinition, projectio base = try projection.toType(baseClassDefinition.bindType(), nullable: false) } else { base = classDefinition.isSealed - ? SupportModules.WinRT.winRTImport(of: .identifier(bindingTypeName)) + ? SupportModules.WinRT.winRTImport(of: .named(bindingTypeName)) : SupportModules.WinRT.composableClass } @@ -39,12 +39,12 @@ internal func writeClassDefinition(_ classDefinition: ClassDefinition, projectio for baseInterface in classDefinition.baseInterfaces { let interfaceDefinition = try baseInterface.interface.definition guard interfaceDefinition.isPublic else { continue } - protocolConformances.append(.identifier(try projection.toProtocolName(interfaceDefinition))) + protocolConformances.append(.named(try projection.toProtocolName(interfaceDefinition))) } if (try? classDefinition.findAttribute(MarshalingBehaviorAttribute.self))?.type == .agile { // SwiftType cannot represent attributed types, so abuse the type name string. - protocolConformances.append(.identifier("@unchecked Sendable")) + protocolConformances.append(.named("@unchecked Sendable")) } try writer.writeClass( @@ -453,7 +453,7 @@ fileprivate func writeDelegatingComposableInitializer( writer.writeInit(visibility: .public, override: true, genericParams: [ "ABIStruct" ], - params: [ SwiftParam(name: "_factory", type: .identifier("ComposableFactory", genericArgs: [ .identifier("ABIStruct") ])) ], + params: [ SwiftParam(name: "_factory", type: .named("ComposableFactory", genericArgs: [.named("ABIStruct") ])) ], throws: true) { writer in writer.writeStatement("try super.init(_factory: _factory)") } diff --git a/Generator/Sources/SwiftWinRT/Writing/EnumDefinition.swift b/Generator/Sources/SwiftWinRT/Writing/EnumDefinition.swift index 6bb58e2f..fbe305d8 100644 --- a/Generator/Sources/SwiftWinRT/Writing/EnumDefinition.swift +++ b/Generator/Sources/SwiftWinRT/Writing/EnumDefinition.swift @@ -28,7 +28,7 @@ fileprivate func writeOpenEnumDefinition(_ enumDefinition: EnumDefinition, proje documentation: projection.getDocumentationComment(enumDefinition), visibility: Projection.toVisibility(enumDefinition.visibility), name: structName, - protocolConformances: [ .identifier("CStyleEnum") ]) { writer throws in + protocolConformances: [.named("CStyleEnum") ]) { writer throws in let rawValueType = try projection.toType(enumDefinition.underlyingType.bindNode()) writer.writeStoredProperty(visibility: .public, declarator: .var, name: "rawValue", type: rawValueType) @@ -56,8 +56,8 @@ fileprivate func writeOpenEnumDefinition(_ enumDefinition: EnumDefinition, proje writer.writeMarkComment("OptionSet and bitwise operators") writer.writeExtension( - type: .identifier(structName), - protocolConformances: [ .identifier("OptionSet") ]) { writer in + type: .named(structName), + protocolConformances: [.named("OptionSet") ]) { writer in // Bitwise not writer.writeFunc( visibility: .public, static: true, operatorLocation: .prefix, name: "~", @@ -91,7 +91,7 @@ fileprivate func writeClosedEnumDefinition(_ enumDefinition: EnumDefinition, pro visibility: Projection.toVisibility(enumDefinition.visibility), name: try projection.toTypeName(enumDefinition), rawValueType: try projection.toType(enumDefinition.underlyingType.bindNode()), - protocolConformances: [ .identifier("ClosedEnum") ]) { writer throws in + protocolConformances: [.named("ClosedEnum") ]) { writer throws in for field in enumDefinition.fields.filter({ $0.visibility == .public && $0.isStatic }) { try writer.writeEnumCase( documentation: projection.getDocumentationComment(field), diff --git a/Generator/Sources/SwiftWinRT/Writing/InterfaceDefinition.swift b/Generator/Sources/SwiftWinRT/Writing/InterfaceDefinition.swift index 0753f4ae..dd7b40ad 100644 --- a/Generator/Sources/SwiftWinRT/Writing/InterfaceDefinition.swift +++ b/Generator/Sources/SwiftWinRT/Writing/InterfaceDefinition.swift @@ -46,8 +46,7 @@ fileprivate func writeProtocol(_ interfaceDefinition: InterfaceDefinition, proje var whereGenericConstraints = OrderedDictionary() for baseInterface in interfaceDefinition.baseInterfaces { let baseInterface = try baseInterface.interface - baseProtocols.append(SwiftType.identifier( - try projection.toProtocolName(baseInterface.definition))) + baseProtocols.append(.named(try projection.toProtocolName(baseInterface.definition))) for (i, genericArg) in baseInterface.genericArgs.enumerated() { let genericParam = baseInterface.definition.genericParams[i] // Ignore generic arguments that are the same as the current interface's generic arguments, @@ -58,7 +57,7 @@ fileprivate func writeProtocol(_ interfaceDefinition: InterfaceDefinition, proje } } - if baseProtocols.isEmpty { baseProtocols.append(SwiftType.identifier("IInspectableProtocol")) } + if baseProtocols.isEmpty { baseProtocols.append(.named("IInspectableProtocol")) } let protocolName = try projection.toProtocolName(interfaceDefinition) try writer.writeProtocol( @@ -138,10 +137,9 @@ fileprivate func writeProtocolTypeAlias(_ interfaceDefinition: InterfaceDefiniti visibility: Projection.toVisibility(interfaceDefinition.visibility), name: try projection.toTypeName(interfaceDefinition), typeParams: interfaceDefinition.genericParams.map { $0.name }, - target: .identifier( - protocolModifier: .any, - name: try projection.toProtocolName(interfaceDefinition), - genericArgs: interfaceDefinition.genericParams.map { .identifier(name: $0.name) })) + target: .named( + try projection.toProtocolName(interfaceDefinition), + genericArgs: interfaceDefinition.genericParams.map {.named($0.name) }).existential()) } fileprivate func writeNonthrowingPropertiesExtension( @@ -151,7 +149,7 @@ fileprivate func writeNonthrowingPropertiesExtension( guard !getSetProperties.isEmpty else { return } let typeName: String = try projection.toProtocolName(interfaceDefinition) - try writer.writeExtension(type: .identifier(typeName)) { writer in + try writer.writeExtension(type: .named(typeName)) { writer in for property in getSetProperties { try writeNonthrowingPropertyImplementation( property: property, static: false, projection: projection, to: writer) diff --git a/Generator/Sources/SwiftWinRT/Writing/NamespaceModules.swift b/Generator/Sources/SwiftWinRT/Writing/NamespaceModules.swift index 7ab97b49..1977af78 100644 --- a/Generator/Sources/SwiftWinRT/Writing/NamespaceModules.swift +++ b/Generator/Sources/SwiftWinRT/Writing/NamespaceModules.swift @@ -69,9 +69,9 @@ fileprivate func writeShortNameTypeAlias( visibility: Projection.toVisibility(typeDefinition.visibility), name: projection.toTypeName(typeDefinition, namespaced: false), typeParams: typeDefinition.genericParams.map { $0.name }, - target: SwiftType.identifier( - name: projection.toTypeName(typeDefinition), - genericArgs: typeDefinition.genericParams.map { SwiftType.identifier(name: $0.name) })) + target: .named( + projection.toTypeName(typeDefinition), + genericArgs: typeDefinition.genericParams.map { .named($0.name) })) if let interface = typeDefinition as? InterfaceDefinition { // We can't typealias protocols, so we define a new one that inherits from the original. @@ -90,7 +90,6 @@ fileprivate func writeShortNameTypeAlias( try writer.writeTypeAlias( visibility: Projection.toVisibility(typeDefinition.visibility), name: projection.toBindingTypeName(typeDefinition, namespaced: false), - target: SwiftType.identifier( - name: projection.toBindingTypeName(typeDefinition))) + target: .named(projection.toBindingTypeName(typeDefinition))) } } \ No newline at end of file diff --git a/Generator/Sources/SwiftWinRT/Writing/NonthrowingProperties.swift b/Generator/Sources/SwiftWinRT/Writing/NonthrowingProperties.swift index 89b53658..42c04157 100644 --- a/Generator/Sources/SwiftWinRT/Writing/NonthrowingProperties.swift +++ b/Generator/Sources/SwiftWinRT/Writing/NonthrowingProperties.swift @@ -15,7 +15,7 @@ internal func writeNonthrowingPropertyImplementation( var propertyType = try projection.toReturnType(property.type) let catchNullResult = projection.isNullAsErrorEligible(try property.type) if catchNullResult { - propertyType = .optional(wrapped: propertyType, implicitUnwrap: true) + propertyType = propertyType.optional(implicitUnwrap: true) } let selfKeyword = `static` ? "Self" : "self" diff --git a/Generator/Sources/SwiftWinRT/Writing/SecondaryInterfaces.swift b/Generator/Sources/SwiftWinRT/Writing/SecondaryInterfaces.swift index 105be856..6f975d55 100644 --- a/Generator/Sources/SwiftWinRT/Writing/SecondaryInterfaces.swift +++ b/Generator/Sources/SwiftWinRT/Writing/SecondaryInterfaces.swift @@ -43,7 +43,7 @@ internal enum SecondaryInterfaces { internal static func writeActivationFactoryDeclaration( classDefinition: ClassDefinition, projection: Projection, to writer: SwiftTypeDefinitionWriter) throws { let storedPropertyName = "_lazyIActivationFactory" - let abiStructType = SwiftType.identifier("SWRT_IActivationFactory") + let abiStructType: SwiftType = .named("SWRT_IActivationFactory") writer.writeStoredProperty( visibility: .private, static: true, declarator: .var, name: storedPropertyName, diff --git a/Generator/Sources/SwiftWinRT/Writing/StructDefinition.swift b/Generator/Sources/SwiftWinRT/Writing/StructDefinition.swift index 1311b1a6..1c2d4ff9 100644 --- a/Generator/Sources/SwiftWinRT/Writing/StructDefinition.swift +++ b/Generator/Sources/SwiftWinRT/Writing/StructDefinition.swift @@ -10,9 +10,9 @@ internal func writeStructDefinition(_ structDefinition: StructDefinition, projec writer.writeImport(exported: true, kind: .struct, module: SupportModules.WinRT.moduleName, symbolName: typeName) } else { let protocolConformances: [SwiftType] = [ - .identifier("Codable"), - .identifier("Hashable"), - .identifier("Sendable") + .named("Codable"), + .named("Hashable"), + .named("Sendable") ] try writer.writeStruct( documentation: projection.getDocumentationComment(structDefinition),