Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize output directories and files #101

Merged
merged 1 commit into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions Generator/Sources/ProjectionModel/SwiftProjection+Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extension SwiftProjection {
public unowned let projection: SwiftProjection
public let name: String
public let flattenNamespaces: Bool
public private(set) var typeDefinitionsByNamespace = OrderedDictionary<String, Set<TypeDefinition>>()
private var _typeDefinitions = OrderedSet<TypeDefinition>()
public private(set) var closedGenericTypesByDefinition = [TypeDefinition: [[TypeNode]]]()
private(set) var weakReferences: Set<Reference> = []

Expand All @@ -17,21 +17,26 @@ extension SwiftProjection {
self.flattenNamespaces = flattenNamespaces
}

public var typeDefinitions: OrderedSet<TypeDefinition> {
_typeDefinitions.sort { $0.fullName < $1.fullName }
return _typeDefinitions
}

public var references: [Module] { weakReferences.map { $0.target } }

public var isEmpty: Bool { typeDefinitionsByNamespace.isEmpty }
public var isEmpty: Bool { _typeDefinitions.isEmpty }

public func addAssembly(_ assembly: Assembly, documentation: AssemblyDocumentation? = nil) {
projection.assembliesToModules[assembly] = AssemblyEntry(module: self, documentation: documentation)
}

public func hasTypeDefinition(_ type: TypeDefinition) -> Bool {
typeDefinitionsByNamespace[Module.getNamespaceOrEmpty(type)]?.contains(type) ?? false
_typeDefinitions.contains(type)
}

public func addTypeDefinition(_ type: TypeDefinition) {
precondition(projection.getModule(type.assembly) === self)
typeDefinitionsByNamespace[Module.getNamespaceOrEmpty(type), default: Set()].insert(type)
_typeDefinitions.append(type)
}

public func addClosedGenericType(_ type: BoundType) {
Expand Down
29 changes: 0 additions & 29 deletions Generator/Sources/SwiftWinRT/Writing/ABIProjectionType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,6 @@ import ProjectionModel
import CodeWriters
import struct Foundation.UUID

internal func writeABIProjectionsFile(module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)

for (_, typeDefinitions) in module.typeDefinitionsByNamespace {
for typeDefinition in typeDefinitions.sorted(by: { $0.fullName < $1.fullName }) {
if let classDefinition = typeDefinition as? ClassDefinition, classDefinition.isStatic { continue }
guard typeDefinition.isPublic,
SupportModules.WinRT.getBuiltInTypeKind(typeDefinition) != .special,
try !typeDefinition.hasAttribute(ApiContractAttribute.self) else { continue }

writer.writeMarkComment(typeDefinition.fullName)
try writeABIProjectionConformance(typeDefinition, genericArgs: nil, projection: module.projection, to: writer)
}
}

let closedGenericTypesByDefinition = module.closedGenericTypesByDefinition
.sorted { $0.key.fullName < $1.key.fullName }
for (typeDefinition, instantiations) in closedGenericTypesByDefinition {
guard SupportModules.WinRT.getBuiltInTypeKind(typeDefinition) != .special else { continue }

for genericArgs in instantiations {
writer.writeMarkComment(try WinRTTypeName.from(type: typeDefinition.bindType(genericArgs: genericArgs)).description)
try writeABIProjectionConformance(typeDefinition, genericArgs: genericArgs, projection: module.projection, to: writer)
}
}
}

/// Writes a type or extension providing the ABIProjection conformance for a given projected WinRT type.
internal func writeABIProjectionConformance(_ typeDefinition: TypeDefinition, genericArgs: [TypeNode]?, projection: SwiftProjection, to writer: SwiftSourceFileWriter) throws {
if SupportModules.WinRT.getBuiltInTypeKind(typeDefinition) == .definitionAndProjection {
Expand Down
35 changes: 14 additions & 21 deletions Generator/Sources/SwiftWinRT/Writing/CAbi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ internal func writeCAbiFile(module: SwiftProjection.Module, toPath path: String)

fileprivate func getSortedEnums(module: SwiftProjection.Module) throws -> [EnumDefinition] {
var enumDefinitions = [EnumDefinition]()
for (_, typeDefinitions) in module.typeDefinitionsByNamespace {
for typeDefinition in typeDefinitions {
guard let enumDefinition = typeDefinition as? EnumDefinition else { continue }
enumDefinitions.append(enumDefinition)
}
for typeDefinition in module.typeDefinitions {
guard let enumDefinition = typeDefinition as? EnumDefinition else { continue }
enumDefinitions.append(enumDefinition)
}

enumDefinitions.sort { $0.fullName < $1.fullName }
Expand All @@ -53,12 +51,9 @@ fileprivate func getSortedEnums(module: SwiftProjection.Module) throws -> [EnumD
fileprivate func getSortedStructs(module: SwiftProjection.Module) throws -> [StructDefinition] {
// Create an initial deterministic ordering of structs
var sortedByFullName = [StructDefinition]()
for (_, typeDefinitions) in module.typeDefinitionsByNamespace {
for typeDefinition in typeDefinitions {
if let structDefinition = typeDefinition as? StructDefinition {
sortedByFullName.append(structDefinition)
}
}
for typeDefinition in module.typeDefinitions {
guard let structDefinition = typeDefinition as? StructDefinition else { continue }
sortedByFullName.append(structDefinition)
}

sortedByFullName.sort { $0.fullName < $1.fullName }
Expand Down Expand Up @@ -90,16 +85,14 @@ fileprivate func getSortedInterfaces(module: SwiftProjection.Module) throws -> [
var interfacesByMangledName = OrderedDictionary<String, BoundType>()

// Add nongeneric type definitions
for (_, typeDefinitions) in module.typeDefinitionsByNamespace {
for typeDefinition in typeDefinitions {
guard typeDefinition.isReferenceType else { continue }
guard !(typeDefinition is ClassDefinition) else { continue }
guard typeDefinition.genericArity == 0 else { continue }

let type = typeDefinition.bindType()
let mangledName = try CAbi.mangleName(type: type)
interfacesByMangledName[mangledName] = type
}
for typeDefinition in module.typeDefinitions {
guard typeDefinition.isReferenceType else { continue }
guard !(typeDefinition is ClassDefinition) else { continue }
guard typeDefinition.genericArity == 0 else { continue }

let type = typeDefinition.bindType()
let mangledName = try CAbi.mangleName(type: type)
interfacesByMangledName[mangledName] = type
}

// Add closed generic type instanciations
Expand Down
39 changes: 1 addition & 38 deletions Generator/Sources/SwiftWinRT/Writing/COMInteropExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,6 @@ import ProjectionModel
import CodeWriters
import struct Foundation.UUID

/// Writes a file that extends COMInterop<I> for every COM interface with
/// methods that translate from the Swift shape to the ABI shape.
internal func writeCOMInteropExtensionsFile(module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)

// Gather bound interfaces and delegates, generic or not, sorted by ABI name
var boundAbiTypes = [(interface: BoundType, abiName: String)]()
for (_, typeDefinitions) in module.typeDefinitionsByNamespace {
for typeDefinition in typeDefinitions {
guard typeDefinition.genericArity == 0 else { continue }
guard typeDefinition is InterfaceDefinition || typeDefinition is DelegateDefinition else { continue }
let boundType = typeDefinition.bindType()
boundAbiTypes.append((boundType, try CAbi.mangleName(type: boundType)))
}
}

for (typeDefinition, instantiations) in module.closedGenericTypesByDefinition {
assert(typeDefinition is InterfaceDefinition || typeDefinition is DelegateDefinition)
for genericArgs in instantiations {
let boundType = typeDefinition.bindType(genericArgs: genericArgs)
boundAbiTypes.append((boundType, try CAbi.mangleName(type: boundType)))
}
}

// Write the COMInterop<I> extension for each interface
boundAbiTypes.sort { $0.abiName < $1.abiName }
for (boundType, _) in boundAbiTypes {
// IReference is special cased, with a single definition for all generic instantiations
guard boundType.definition.fullName != "Windows.Foundation.IReference`1" else { continue }

writer.writeMarkComment(try WinRTTypeName.from(type: boundType).description)
try writeCOMInteropExtension(abiType: boundType, projection: module.projection, to: writer)
}
}

fileprivate enum ABIInterfaceUsage {
case activationFactory
case composableFactory
Expand All @@ -65,7 +28,7 @@ fileprivate enum ABIInterfaceUsage {
}
}

fileprivate func writeCOMInteropExtension(abiType: BoundType, projection: SwiftProjection, to writer: SwiftSourceFileWriter) throws {
internal func writeCOMInteropExtension(abiType: BoundType, projection: SwiftProjection, to writer: SwiftSourceFileWriter) throws {
let abiSwiftType = try projection.toABIType(abiType)
let visibility: SwiftVisibility = abiType.genericArgs.isEmpty ? .public : .internal

Expand Down
8 changes: 3 additions & 5 deletions Generator/Sources/SwiftWinRT/Writing/ExeManifest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ internal func writeExeManifestFile(projectionConfig: ProjectionConfig, projectio
guard let moduleConfig = projectionConfig.modules[module.name],
let fileNameInManifest = moduleConfig.fileNameInManifest else { continue }

for typeDefinitions in module.typeDefinitionsByNamespace.values {
for typeDefinition in typeDefinitions {
guard typeDefinition is ClassDefinition else { continue }
activatableClassesPerFileName[fileNameInManifest, default: []].append(typeDefinition.fullName)
}
for typeDefinition in module.typeDefinitions {
guard typeDefinition is ClassDefinition else { continue }
activatableClassesPerFileName[fileNameInManifest, default: []].append(typeDefinition.fullName)
}
}

Expand Down
12 changes: 0 additions & 12 deletions Generator/Sources/SwiftWinRT/Writing/NamespaceAlias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@ import CodeWriters
import DotNetMetadata
import ProjectionModel

internal func writeNamespaceAliasesFile(typeDefinitions: [TypeDefinition], module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writer.writeImport(module: module.name)

for typeDefinition in typeDefinitions.sorted(by: { $0.fullName < $1.fullName }) {
guard typeDefinition.isPublic else { continue }

try writeNamespaceAlias(typeDefinition, projection: module.projection, to: writer)
}
}

internal func writeNamespaceAlias(_ typeDefinition: TypeDefinition, projection: SwiftProjection, to writer: SwiftSourceFileWriter) throws {
try writer.writeTypeAlias(
visibility: SwiftProjection.toVisibility(typeDefinition.visibility),
Expand Down
11 changes: 10 additions & 1 deletion Generator/Sources/SwiftWinRT/Writing/SwiftPackageFile.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CodeWriters
import Collections
import DotNetMetadata
import ProjectionModel
import struct Foundation.URL
Expand Down Expand Up @@ -47,7 +48,15 @@ func writeSwiftPackageFile(_ projection: SwiftProjection, supportPackageLocation

// Namespace modules
if !module.flattenNamespaces {
for (namespace, _) in module.typeDefinitionsByNamespace {
var namespaces = OrderedSet<String>()
for typeDefinition in module.typeDefinitions {
guard let namespace = typeDefinition.namespace else { continue }
namespaces.append(namespace)
}

namespaces.sort()

for namespace in namespaces {
var namespaceModuleTarget = SwiftPackage.Target(
name: module.getNamespaceModuleName(namespace: namespace))
let compactNamespace = SwiftProjection.toCompactNamespace(namespace)
Expand Down
113 changes: 94 additions & 19 deletions Generator/Sources/SwiftWinRT/writeProjectionFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,112 @@ internal func writeProjectionFiles(_ projection: SwiftProjection, generateComman

try writeCAbiFile(module: module, toPath: "\(abiModuleIncludeDirectoryPath)\\\(module.name).h")
try writeClassLoaderGlobalFile(module: module, toPath: "\(assemblyModuleDirectoryPath)\\ClassLoader.swift")
try writeCOMInteropExtensionsFile(module: module, toPath: "\(assemblyModuleDirectoryPath)\\COMInterop.swift")
try writeABIProjectionsFile(module: module, toPath: "\(assemblyModuleDirectoryPath)\\ABIProjections.swift")

for (namespace, typeDefinitions) in module.typeDefinitionsByNamespace {
let compactNamespace = SwiftProjection.toCompactNamespace(namespace)
print("Generating types for namespace \(namespace)...")
for typeDefinition in module.typeDefinitions + Array(module.closedGenericTypesByDefinition.keys) {
guard try hasSwiftDefinition(typeDefinition) else { continue }

let compactNamespace = SwiftProjection.toCompactNamespace(typeDefinition.namespace!)
let assemblyNamespaceDirectoryPath = "\(assemblyModuleDirectoryPath)\\\(compactNamespace)"

var typeDefinitions = Array(typeDefinitions)
try typeDefinitions.removeAll {
try !$0.isPublic || SupportModules.WinRT.getBuiltInTypeKind($0) == .special || $0.hasAttribute(ApiContractAttribute.self)
if module.typeDefinitions.contains(typeDefinition) {
try writeTypeDefinitionFile(typeDefinition, module: module, toPath: "\(assemblyNamespaceDirectoryPath)\\\(typeDefinition.nameWithoutGenericSuffix).swift")
}
typeDefinitions.sort { $0.fullName < $1.fullName }

// Write the type definition file
for typeDefinition in typeDefinitions {
let filePath = "\(assemblyModuleDirectoryPath)\\\(compactNamespace)\\\(typeDefinition.nameWithoutGenericSuffix).swift"
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: filePath, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)
try writeTypeDefinition(typeDefinition, projection: module.projection, to: writer)

if (typeDefinition as? ClassDefinition)?.isStatic != true {
try writeABIProjectionConformanceFile(typeDefinition, module: module,
toPath: "\(assemblyNamespaceDirectoryPath)\\Projections\\\(typeDefinition.nameWithoutGenericSuffix)+Projection.swift")
}
}

// Write the namespace aliases file
if !module.flattenNamespaces {
for abiType in try getABITypes(module: module) {
guard let namespace = abiType.definition.namespace else { continue }
let compactNamespace = SwiftProjection.toCompactNamespace(namespace)
let mangledName = try CAbi.mangleName(type: abiType)
try writeCOMInteropExtensionFile(abiType: abiType, module: module,
toPath: "\(assemblyModuleDirectoryPath)\\\(compactNamespace)\\COMInterop\\\(mangledName).swift")
}

if !module.flattenNamespaces {
let typeDefinitionsByNamespace = OrderedDictionary(grouping: module.typeDefinitions, by: { $0.namespace })
for (namespace, typeDefinitions) in typeDefinitionsByNamespace {
let typeDefinitions = try typeDefinitions.filter(hasSwiftDefinition)
guard !typeDefinitions.isEmpty else { continue }

let compactNamespace = SwiftProjection.toCompactNamespace(namespace!)
let namespaceAliasesPath = "\(moduleRootPath)\\Namespaces\\\(compactNamespace)\\Aliases.swift"
try writeNamespaceAliasesFile(typeDefinitions: typeDefinitions, module: module, toPath: namespaceAliasesPath)
}
}
}
}

fileprivate func hasSwiftDefinition(_ typeDefinition: TypeDefinition) throws -> Bool {
return try SupportModules.WinRT.getBuiltInTypeKind(typeDefinition) != .special
&& !typeDefinition.hasAttribute(ApiContractAttribute.self)
&& typeDefinition.isPublic
}

fileprivate func writeTypeDefinitionFile(_ typeDefinition: TypeDefinition, module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)
try writeTypeDefinition(typeDefinition, projection: module.projection, to: writer)
}

fileprivate func writeABIProjectionConformanceFile(_ typeDefinition: TypeDefinition, module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)

if module.typeDefinitions.contains(typeDefinition) {
try writeABIProjectionConformance(typeDefinition, genericArgs: nil, projection: module.projection, to: writer)
}

for genericArgs in module.closedGenericTypesByDefinition[typeDefinition] ?? [] {
let boundType = typeDefinition.bindType(genericArgs: genericArgs)
writer.writeMarkComment(try WinRTTypeName.from(type: boundType).description)
try writeABIProjectionConformance(typeDefinition, genericArgs: genericArgs, projection: module.projection, to: writer)
}
}

fileprivate func getABITypes(module: SwiftProjection.Module) throws -> [BoundType] {
var abiTypes = [BoundType]()
for typeDefinition in module.typeDefinitions {
guard typeDefinition.genericArity == 0 else { continue }
guard typeDefinition is InterfaceDefinition || typeDefinition is DelegateDefinition else { continue }
abiTypes.append(typeDefinition.bindType())
}

for (typeDefinition, instantiations) in module.closedGenericTypesByDefinition {
// IReference<T> is implemented generically in the support module.
if typeDefinition.namespace == "Windows.Foundation", typeDefinition.name == "IReference`1" { continue }
for genericArgs in instantiations {
abiTypes.append(typeDefinition.bindType(genericArgs: genericArgs))
}
}

return abiTypes
}

fileprivate func writeCOMInteropExtensionFile(abiType: BoundType, module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writeModulePreamble(module, to: writer)
try writeCOMInteropExtension(abiType: abiType, projection: module.projection, to: writer)
}

internal func writeNamespaceAliasesFile(typeDefinitions: [TypeDefinition], module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
writer.writeImport(module: module.name)

for typeDefinition in typeDefinitions.sorted(by: { $0.fullName < $1.fullName }) {
guard typeDefinition.isPublic else { continue }

try writeNamespaceAlias(typeDefinition, projection: module.projection, to: writer)
}
}

fileprivate func writeClassLoaderGlobalFile(module: SwiftProjection.Module, toPath path: String) throws {
let writer = SwiftSourceFileWriter(output: FileTextOutputStream(path: path, directoryCreation: .ancestors))
writeGeneratedCodePreamble(to: writer)
Expand Down
Loading