Skip to content

Commit

Permalink
Split SupportModule into COM and WinRT. (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlabelle authored Mar 23, 2024
1 parent 66e1d48 commit 43ce04c
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 121 deletions.
81 changes: 0 additions & 81 deletions Generator/Sources/ProjectionModel/SupportModule.swift

This file was deleted.

86 changes: 86 additions & 0 deletions Generator/Sources/ProjectionModel/SupportModules.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import CodeWriters
import DotNetMetadata

public enum SupportModules {
public enum COM {}
public enum WinRT {}
}

extension SupportModules.COM {
public static var moduleName: String { "COM" }

public static var implementABIMethodFunc: String { "\(moduleName).implementABIMethod" }

public static var iunknownPointer: SwiftType { .chain(moduleName, "IUnknownPointer") }
public static var comInterfaceID: SwiftType { .chain(moduleName, "COMInterfaceID") }
public static var comIUnknownStruct: SwiftType { .chain(moduleName, "COMIUnknownStruct") }
public static var nullResult: SwiftType { .chain(moduleName, "NullResult") }

public static var hresult: SwiftType { .chain(moduleName, "HResult") }

public static var abiProjection: SwiftType { .chain(moduleName, "ABIProjection") }
public static var abiInertProjection: SwiftType { .chain(moduleName, "ABIInertProjection") }
public static var boolProjection: SwiftType { .chain(moduleName, "BoolProjection") }
public static var wideCharProjection: SwiftType { .chain(moduleName, "WideCharProjection") }
public static var guidProjection: SwiftType { .chain(moduleName, "GUIDProjection") }
public static var hresultProjection: SwiftType { .chain(moduleName, "HResultProjection") }

public static var comProjection: SwiftType { .chain(moduleName, "COMProjection") }
public static var comTwoWayProjection: SwiftType { .chain(moduleName, "COMTwoWayProjection") }

public static var comExportedInterface: SwiftType { .chain(moduleName, "COMExportedInterface") }

public static var comReference: SwiftType { .chain(moduleName, "COMReference") }
public static func comReference(to type: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("COMReference", genericArgs: [type]) ])
}

public static var comLazyReference: SwiftType { .chain(moduleName, "COMLazyReference") }
public static func comLazyReference(to type: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("COMLazyReference", genericArgs: [type]) ])
}

public static var comLazyReference_getInterop: String { "getInterop" }
public static var comLazyReference_getPointer: String { "getPointer" }

public static var comInterop: SwiftType { .chain(moduleName, "COMInterop") }
public static func comInterop(of type: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("COMInterop", genericArgs: [type]) ])
}

public static func comArray(of type: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("COMArray", genericArgs: [type]) ])
}
}

extension SupportModules.WinRT {
public static var moduleName: String { "WindowsRuntime" }

public static var comIInspectableStruct: SwiftType { .chain(moduleName, "COMIInspectableStruct") }
public static var eventRegistration: SwiftType { .chain(moduleName, "EventRegistration") }
public static var eventRegistrationToken: SwiftType { .chain(moduleName, "EventRegistrationToken") }
public static var hstringProjection: SwiftType { .chain(moduleName, "HStringProjection") }
public static var iinspectable: SwiftType { .chain(moduleName, "IInspectable") }
public static var iinspectableProjection: SwiftType { .chain(moduleName, "IInspectableProjection") }

public static var winRTProjection: SwiftType { .chain(moduleName, "WinRTProjection") }
public static var winRTTwoWayProjection: SwiftType { .chain(moduleName, "WinRTTwoWayProjection") }

public static func winRTArrayProjection(of type: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("WinRTArrayProjection", genericArgs: [type]) ])
}

public static var winRTClassLoader: SwiftType { .chain(moduleName, "WinRTClassLoader") }
}

extension SupportModules.WinRT {
public static func hasBuiltInProjection(_ typeDefinition: TypeDefinition) -> Bool {
if typeDefinition.namespace == "Windows.Foundation" {
switch typeDefinition.name {
case "EventRegistrationToken", "HResult", "IReference`1": return true
default: return false
}
}
return false
}
}
24 changes: 12 additions & 12 deletions Generator/Sources/ProjectionModel/SwiftProjection+types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ extension SwiftProjection {
let elementProjection = try getTypeProjection(element)
let swiftType = SwiftType.array(element: elementProjection.swiftType)
return TypeProjection(
abiType: SupportModule.comArray(of: elementProjection.abiType),
abiType: SupportModules.COM.comArray(of: elementProjection.abiType),
abiDefaultValue: .defaultInitializer,
swiftType: swiftType,
swiftDefaultValue: "[]",
projectionType: SupportModule.winRTArrayProjection(of: elementProjection.projectionType),
projectionType: SupportModules.WinRT.winRTArrayProjection(of: elementProjection.projectionType),
kind: .array)

default:
Expand Down Expand Up @@ -151,7 +151,7 @@ extension SwiftProjection {
abiDefaultValue: .`false`,
swiftType: .bool,
swiftDefaultValue: .`false`,
projectionType: SupportModule.boolProjection,
projectionType: SupportModules.COM.boolProjection,
kind: .inert)
case .integer(.uint8): return .numeric(.uint(bits: 8))
case .integer(.int16): return .numeric(.int(bits: 16))
Expand All @@ -168,31 +168,31 @@ extension SwiftProjection {
abiDefaultValue: .zero,
swiftType: .chain("Swift", "Unicode", "UTF16", "CodeUnit"),
swiftDefaultValue: .zero,
projectionType: SupportModule.wideCharProjection,
projectionType: SupportModules.COM.wideCharProjection,
kind: .identity)
case .guid:
return TypeProjection(
abiType: .chain(abiModuleName, CAbi.guidName),
abiDefaultValue: .defaultInitializer,
swiftType: .chain("Foundation", "UUID"),
swiftDefaultValue: .defaultInitializer,
projectionType: SupportModule.guidProjection,
projectionType: SupportModules.COM.guidProjection,
kind: .inert)
case .string:
return .init(
abiType: .optional(wrapped: .chain(abiModuleName, CAbi.hstringName)),
abiDefaultValue: .nil,
swiftType: .string,
swiftDefaultValue: .emptyString,
projectionType: SupportModule.hstringProjection,
projectionType: SupportModules.WinRT.hstringProjection,
kind: .allocating)
case .object:
return .init(
abiType: .optional(wrapped: .chain("IInspectableProjection", "COMPointer")),
abiDefaultValue: .nil,
swiftType: .optional(wrapped: SupportModule.iinspectable),
swiftType: .optional(wrapped: SupportModules.WinRT.iinspectable),
swiftDefaultValue: .nil,
projectionType: SupportModule.iinspectableProjection,
projectionType: SupportModules.WinRT.iinspectableProjection,
kind: .allocating)
}
}
Expand All @@ -208,18 +208,18 @@ extension SwiftProjection {
return TypeProjection(
abiType: .chain(abiModuleName, CAbi.eventRegistrationTokenName),
abiDefaultValue: .defaultInitializer,
swiftType: SupportModule.eventRegistrationToken,
swiftType: SupportModules.WinRT.eventRegistrationToken,
swiftDefaultValue: .defaultInitializer,
projectionType: SupportModule.eventRegistrationToken,
projectionType: SupportModules.WinRT.eventRegistrationToken,
kind: .inert)

case "HResult":
return TypeProjection(
abiType: .chain(abiModuleName, CAbi.hresultName),
abiDefaultValue: .zero,
swiftType: SupportModule.hresult,
swiftType: SupportModules.COM.hresult,
swiftDefaultValue: .defaultInitializer,
projectionType: SupportModule.hresultProjection,
projectionType: SupportModules.COM.hresultProjection,
kind: .inert)

default:
Expand Down
16 changes: 8 additions & 8 deletions Generator/Sources/SwiftWinRT/Writing/ABIProjectionType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal func writeABIProjectionsFile(module: SwiftProjection.Module, toPath pat
for typeDefinition in typeDefinitions.sorted(by: { $0.fullName < $1.fullName }) {
if let classDefinition = typeDefinition as? ClassDefinition, classDefinition.isStatic { continue }
guard typeDefinition.isPublic,
!SupportModule.hasBuiltInProjection(typeDefinition),
!SupportModules.WinRT.hasBuiltInProjection(typeDefinition),
try !typeDefinition.hasAttribute(ApiContractAttribute.self) else { continue }

writer.writeMarkComment(typeDefinition.fullName)
Expand All @@ -25,7 +25,7 @@ internal func writeABIProjectionsFile(module: SwiftProjection.Module, toPath pat
let closedGenericTypesByDefinition = module.closedGenericTypesByDefinition
.sorted { $0.key.fullName < $1.key.fullName }
for (typeDefinition, instantiations) in closedGenericTypesByDefinition {
guard !SupportModule.hasBuiltInProjection(typeDefinition) else { continue }
guard !SupportModules.WinRT.hasBuiltInProjection(typeDefinition) else { continue }

for genericArgs in instantiations {
writer.writeMarkComment(try WinRTTypeName.from(type: typeDefinition.bindType(genericArgs: genericArgs)).description)
Expand Down Expand Up @@ -98,7 +98,7 @@ fileprivate func writeStructProjectionExtension(
projection: SwiftProjection,
to writer: SwiftSourceFileWriter) throws {
let isInert = try projection.isProjectionInert(structDefinition)
let abiProjectionProtocol = isInert ? SupportModule.abiInertProjection : SupportModule.abiProjection
let abiProjectionProtocol = isInert ? SupportModules.COM.abiInertProjection : SupportModules.COM.abiProjection

// TODO: Support strings and IReference<T> field types (non-inert)
// extension <struct>: ABIInertProjection
Expand Down Expand Up @@ -237,7 +237,7 @@ fileprivate func writeClassProjectionType(
let projectionTypeName = try projection.toProjectionTypeName(classDefinition)
try writer.writeEnum(
visibility: SwiftProjection.toVisibility(classDefinition.visibility),
name: projectionTypeName, protocolConformances: [ SupportModule.winRTProjection ]) { writer throws in
name: projectionTypeName, protocolConformances: [ SupportModules.WinRT.winRTProjection ]) { writer throws in
let typeName = try projection.toTypeName(classDefinition)
let composable = try classDefinition.hasAttribute(ComposableAttribute.self)

Expand All @@ -256,7 +256,7 @@ fileprivate func writeClassProjectionType(
toCOMBody: { writer, paramName in
if composable {
let propertyName = SecondaryInterfaces.getPropertyName(defaultInterface)
writer.writeStatement("try \(SupportModule.comReference)(addingRef: object.\(propertyName).this)")
writer.writeStatement("try \(SupportModules.COM.comReference)(addingRef: object.\(propertyName).this)")
}
else {
// WinRTImport exposes comPointer
Expand Down Expand Up @@ -290,7 +290,7 @@ fileprivate func writeInterfaceOrDelegateProjectionType(
to writer: some SwiftDeclarationWriter) throws {
precondition(type.definition is InterfaceDefinition || type.definition is DelegateDefinition)
let projectionProtocol = type.definition is InterfaceDefinition
? SupportModule.winRTTwoWayProjection : SupportModule.comTwoWayProjection
? SupportModules.WinRT.winRTTwoWayProjection : SupportModules.COM.comTwoWayProjection

try writer.writeEnum(
visibility: SwiftProjection.toVisibility(type.definition.visibility),
Expand Down Expand Up @@ -355,7 +355,7 @@ internal func writeCOMProjectionConformance(
target: try projection.toABIVirtualTableType(abiType))

// public static var interfaceID: COM.COMInterfaceID { COMInterface.iid }
writer.writeComputedProperty(visibility: .public, static: true, name: "interfaceID", type: SupportModule.comInterfaceID) { writer in
writer.writeComputedProperty(visibility: .public, static: true, name: "interfaceID", type: SupportModules.COM.comInterfaceID) { writer in
writer.writeStatement("COMInterface.iid")
}

Expand All @@ -366,7 +366,7 @@ internal func writeCOMProjectionConformance(
initialValue: "\"\(runtimeClassName)\"")
}

let comReferenceType = SupportModule.comReference(to: .identifier("COMInterface"))
let comReferenceType = SupportModules.COM.comReference(to: .identifier("COMInterface"))

try writer.writeFunc(
visibility: .public, static: true, name: "toSwift",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fileprivate func writeCOMInteropExtension(abiType: BoundType, projection: SwiftP
// Mark the COM interface struct as conforming to IUnknown (delegates) or IInspectable (interfaces)
// @retroactive is only supported in Swift 5.10 and above.
let group = writer.output.allocateVerticalGrouping()
let comStructProtocol = abiType.definition is InterfaceDefinition ? SupportModule.comIInspectableStruct : SupportModule.comIUnknownStruct
let comStructProtocol = abiType.definition is InterfaceDefinition ? SupportModules.WinRT.comIInspectableStruct : SupportModules.COM.comIUnknownStruct
writer.output.writeFullLine(grouping: group, "#if swift(>=5.10)")
writer.output.writeFullLine(grouping: group, "extension \(abiSwiftType): @retroactive \(comStructProtocol) {}")
writer.output.writeFullLine(grouping: group, "#else")
Expand All @@ -85,7 +85,7 @@ fileprivate func writeCOMInteropExtension(abiType: BoundType, projection: SwiftP
initialValue: try toIIDExpression(WindowsMetadata.getInterfaceID(abiType)))
}

try writer.writeExtension(type: SupportModule.comInterop, whereClauses: [ "Interface == \(abiSwiftType)" ]) { writer in
try writer.writeExtension(type: SupportModules.COM.comInterop, whereClauses: [ "Interface == \(abiSwiftType)" ]) { writer in
let interfaceUsage = try ABIInterfaceUsage.from(typeDefinition: abiType.definition)
for method in abiType.definition.methods {
// For delegates, only expose the Invoke method
Expand Down
Loading

0 comments on commit 43ce04c

Please sign in to comment.