Skip to content

Commit

Permalink
More @available's so warnings don't show up in generated code
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlabelle committed Dec 29, 2024
1 parent 60afba4 commit 58b1939
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ public struct SwiftSourceFileWriter: SwiftDeclarationWriter {
}

public func writeExtension(
attributes: [SwiftAttribute] = [],
type: SwiftType,
protocolConformances: [SwiftType] = [],
whereClauses: [String] = [],
members: (SwiftTypeDefinitionWriter) throws -> Void) rethrows {

var output = output
output.beginLine(group: .alone)
writeAttributes(attributes)
output.write("extension ")
type.write(to: &output)
writeInheritanceClause(protocolConformances)
Expand Down
17 changes: 12 additions & 5 deletions Generator/Sources/ProjectionModel/Projection+conversion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ extension Projection {
: definitionBindingType.member(try Projection.toBindingInstantiationTypeName(genericArgs: type.genericArgs))
}

public static func getAvailableAttribute(
_ attributable: any Attributable,
deprecator: (any Attributable)? = nil) throws -> SwiftAttribute? {
guard let deprecatedAttribute = try attributable.findAttribute(WindowsMetadata.DeprecatedAttribute.self)
?? deprecator?.findAttribute(WindowsMetadata.DeprecatedAttribute.self) else { return nil }
// DeprecatedAttribute tells us the ContractVersion in which an attribute was deprecated,
// but since apps should run on any future OS version, we can mark it as unconditionally deprecated.
return SwiftAttribute("available(*, deprecated, message: \"\(deprecatedAttribute.message)\")")
}

public static func getAttributes(
_ attributable: any Attributable,
deprecator: (any Attributable)? = nil) throws -> [SwiftAttribute] {
Expand All @@ -99,11 +109,8 @@ extension Projection {
}

// Also add deprecation attributes
if let deprecatedAttribute = try attributable.findAttribute(WindowsMetadata.DeprecatedAttribute.self)
?? deprecator?.findAttribute(WindowsMetadata.DeprecatedAttribute.self) {
// DeprecatedAttribute tells us the ContractVersion in which an attribute was deprecated,
// but since apps should run on any future OS version, we can mark it as unconditionally deprecated.
attributes.append(SwiftAttribute("available(*, deprecated, message: \"\(deprecatedAttribute.message)\")"))
if let availableAttribute = try getAvailableAttribute(attributable, deprecator: deprecator) {
attributes.append(availableAttribute)
}

return attributes
Expand Down
40 changes: 28 additions & 12 deletions Generator/Sources/SwiftWinRT/Writing/ABIBinding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,7 @@ internal func writeABIBindingConformance(_ typeDefinition: TypeDefinition, gener

if let enumDefinition = typeDefinition as? EnumDefinition {
assert(genericArgs == nil)
let enumBindingProtocol = try projection.isSwiftEnumEligible(enumDefinition)
? SupportModules.WinRT.closedEnumBinding : SupportModules.WinRT.openEnumBinding
try writer.writeExtension(
type: projection.toTypeReference(enumDefinition.bindType()),
protocolConformances: [ enumBindingProtocol ]) { writer in
// public static var typeName: String { "..." }
try writeTypeNameProperty(type: enumDefinition.bindType(), to: writer)

// public static var ireferenceID: COM.COMInterfaceID { .init(...) }
// public static var ireferenceArrayID: COM.COMInterfaceID { .init(...) }
try writeIReferenceIDProperties(boxableType: enumDefinition.bindType(), to: writer)
}
try writeEnumBindingExtension(enumDefinition, projection: projection, to: writer)
return
}

Expand Down Expand Up @@ -69,6 +58,7 @@ internal func writeABIBindingConformance(_ typeDefinition: TypeDefinition, gener
// internal final class Boolean: WinRTBinding... {}
// }
try writer.writeExtension(
attributes: [ Projection.getAvailableAttribute(typeDefinition) ].compactMap { $0 },
type: projection.toBindingType(typeDefinition)) { writer in
try writeInterfaceOrDelegateBindingType(
typeDefinition.bindType(genericArgs: genericArgs),
Expand All @@ -80,11 +70,32 @@ internal func writeABIBindingConformance(_ typeDefinition: TypeDefinition, gener
// Generic type definition. Create a namespace for projections of specializations.
// public enum IVectorBinding {}
try writer.writeEnum(
attributes: [ Projection.getAvailableAttribute(typeDefinition) ].compactMap { $0 },
visibility: Projection.toVisibility(typeDefinition.visibility),
name: projection.toBindingTypeName(typeDefinition)) { _ in }
}
}

/// Writes an extension to an enum to provide the ABIBinding conformance.
fileprivate func writeEnumBindingExtension(
_ enumDefinition: EnumDefinition,
projection: Projection,
to writer: SwiftSourceFileWriter) throws {
let enumBindingProtocol = try projection.isSwiftEnumEligible(enumDefinition)
? SupportModules.WinRT.closedEnumBinding : SupportModules.WinRT.openEnumBinding
try writer.writeExtension(
attributes: [ Projection.getAvailableAttribute(enumDefinition) ].compactMap { $0 },
type: projection.toTypeReference(enumDefinition.bindType()),
protocolConformances: [ enumBindingProtocol ]) { writer in
// public static var typeName: String { "..." }
try writeTypeNameProperty(type: enumDefinition.bindType(), to: writer)

// public static var ireferenceID: COM.COMInterfaceID { .init(...) }
// public static var ireferenceArrayID: COM.COMInterfaceID { .init(...) }
try writeIReferenceIDProperties(boxableType: enumDefinition.bindType(), to: writer)
}
}

/// Writes an extension to a struct to provide the ABIBinding conformance.
fileprivate func writeStructBindingExtension(
_ structDefinition: StructDefinition,
Expand All @@ -99,6 +110,7 @@ fileprivate func writeStructBindingExtension(

// extension <struct>: IReferenceableBinding[, PODBinding]
try writer.writeExtension(
attributes: [ Projection.getAvailableAttribute(structDefinition) ].compactMap { $0 },
type: .named(projection.toTypeName(structDefinition)),
protocolConformances: protocolConformances) { writer in

Expand Down Expand Up @@ -261,7 +273,10 @@ fileprivate func writeClassBindingType(
? SupportModules.WinRT.composableClassBinding
: SupportModules.WinRT.runtimeClassBinding

// Runtimeclass bindings are classes so they can be found using NSClassFromString,
// which allows supporting instantiating the most derived class wrapper when returned from WinRT.
try writer.writeClass(
attributes: [ Projection.getAvailableAttribute(classDefinition) ].compactMap { $0 },
visibility: Projection.toVisibility(classDefinition.visibility),
name: projection.toBindingTypeName(classDefinition),
protocolConformances: [ bindingProtocol ]) { writer throws in
Expand Down Expand Up @@ -362,6 +377,7 @@ fileprivate func writeInterfaceOrDelegateBindingType(
// Projections of generic instantiations are not owned by any specific module.
// Making them internal avoids clashes between redundant definitions across modules.
try writer.writeEnum(
attributes: [ Projection.getAvailableAttribute(type.definition) ].compactMap { $0 },
visibility: type.genericArgs.isEmpty ? Projection.toVisibility(type.definition.visibility) : .internal,
name: name,
protocolConformances: [ bindingProtocol ]) { writer throws in
Expand Down
13 changes: 8 additions & 5 deletions Generator/Sources/SwiftWinRT/Writing/InterfaceDefinition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,14 @@ fileprivate func writeProtocol(_ interfaceDefinition: InterfaceDefinition, proje
}

fileprivate func writeProtocolTypeAlias(_ interfaceDefinition: InterfaceDefinition, projection: Projection, to writer: SwiftSourceFileWriter) throws {
writer.writeTypeAlias(
try writer.writeTypeAlias(
documentation: projection.getDocumentationComment(interfaceDefinition),
attributes: [ Projection.getAvailableAttribute(interfaceDefinition) ].compactMap { $0 },
visibility: Projection.toVisibility(interfaceDefinition.visibility),
name: try projection.toTypeName(interfaceDefinition),
name: projection.toTypeName(interfaceDefinition),
typeParams: interfaceDefinition.genericParams.map { $0.name },
target: .named(
try projection.toProtocolName(interfaceDefinition),
projection.toProtocolName(interfaceDefinition),
genericArgs: interfaceDefinition.genericParams.map {.named($0.name) }).existential())
}

Expand All @@ -152,8 +153,10 @@ fileprivate func writeNonthrowingPropertiesExtension(
let getSetProperties = try interfaceDefinition.properties.filter { try $0.getter != nil }
guard !getSetProperties.isEmpty else { return }

let typeName: String = try projection.toProtocolName(interfaceDefinition)
try writer.writeExtension(type: .named(typeName)) { writer in
let protocolType = SwiftType.named(try projection.toProtocolName(interfaceDefinition))
try writer.writeExtension(
attributes: [ Projection.getAvailableAttribute(interfaceDefinition) ].compactMap { $0 },
type: protocolType) { writer in
for property in getSetProperties {
try writeNonthrowingPropertyImplementation(
property: property, static: false, projection: projection, to: writer)
Expand Down

0 comments on commit 58b1939

Please sign in to comment.