1
0
Fork 0
gobject-generator/Sources/SwiftGtkGenCore/Analysis.swift
Brendan Szymanski 1330f2bd25 Initial commit: SwiftGtkGen GIR-to-Swift binding generator
Extracted from gtk-swift monorepo. Previous history
contains 38 commits across the full Phase 1 development
including GIR XML parsing, IR model, analysis engine,
code generation, CLI, plugins, and documentation.
2026-07-01 03:27:41 -04:00

127 lines
5.2 KiB
Swift

/// The result of analyzing a GIR repository against a `GenerationConfig`.
///
/// Contains the resolved class hierarchy, the classification of each type
/// (generate, manual, or ignore), and any per-type or per-function overrides
/// from the configuration. This result drives the subsequent code-generation
/// phase.
public struct AnalysisResult {
/// Maps each type name to its parent type name, forming an inheritance tree.
///
/// Keys are fully-qualified type names (e.g. `"Gtk.Widget"`); values are the
/// fully-qualified parent name.
public var classHierarchy: [String: String]
/// The set of fully-qualified type names that should have Swift bindings generated.
public var generatedTypes: Set<String>
/// The set of fully-qualified type names that are implemented manually and
/// should be excluded from generation.
public var manualTypes: Set<String>
/// The set of fully-qualified type names that should be skipped entirely.
public var ignoredTypes: Set<String>
/// Per-type overrides keyed by fully-qualified type name.
public var classOverrides: [String: ObjectOverrides]
/// Per-function overrides keyed by `"ClassName.functionName"`.
public var functionOverrides: [String: FunctionOverrides]
/// Creates an analysis result from the given component values.
///
/// - Parameters:
/// - classHierarchy: Inheritance map from each type to its parent.
/// - generatedTypes: Types that should be generated.
/// - manualTypes: Types that are implemented manually.
/// - ignoredTypes: Types that should be omitted.
/// - classOverrides: Per-type override configuration.
/// - functionOverrides: Per-function override configuration.
public init(classHierarchy: [String: String] = [:], generatedTypes: Set<String> = [],
manualTypes: Set<String> = [], ignoredTypes: Set<String> = [],
classOverrides: [String: ObjectOverrides] = [:],
functionOverrides: [String: FunctionOverrides] = [:]) {
self.classHierarchy = classHierarchy
self.generatedTypes = generatedTypes
self.manualTypes = manualTypes
self.ignoredTypes = ignoredTypes
self.classOverrides = classOverrides
self.functionOverrides = functionOverrides
}
}
/// Analyzes a GIR repository against a `GenerationConfig` to produce an `AnalysisResult`.
///
/// The analyzer walks the repository's type hierarchy and applies the
/// configuration's generate/manual/ignore lists and per-type overrides.
public struct Analyzer {
/// The generation configuration that guides the analysis.
public let config: GenerationConfig
/// Creates an analyzer with the given generation configuration.
///
/// - Parameter config: The configuration specifying which types to
/// generate, handle manually, or ignore, along with any overrides.
public init(config: GenerationConfig) {
self.config = config
}
/// Analyzes the provided GIR repository and returns the classification result.
///
/// The analysis builds a class inheritance hierarchy from the repository,
/// classifies each type according to the configuration's `generate`,
/// `manual`, and `ignore` lists, and extracts per-type and per-function
/// overrides.
///
/// - Parameter repository: The parsed GIR repository to analyze.
/// - Returns: An `AnalysisResult` containing the resolved hierarchy, type
/// classifications, and overrides.
public func analyze(repository: Repository) -> AnalysisResult {
var classHierarchy: [String: String] = [:]
var generatedTypes: Set<String> = []
var manualTypes: Set<String> = []
var ignoredTypes: Set<String> = []
var classOverrides: [String: ObjectOverrides] = [:]
var functionOverrides: [String: FunctionOverrides] = [:]
for ns in repository.namespaces {
for cls in ns.classes {
let fullName = "\(ns.name).\(cls.name)"
if let parent = cls.parent {
let parentFullName = parent.contains(".") ? parent : "\(ns.name).\(parent)"
classHierarchy[fullName] = parentFullName
}
}
}
for fullName in config.generate {
generatedTypes.insert(fullName)
}
for fullName in config.manual {
manualTypes.insert(fullName)
}
for fullName in config.ignore {
ignoredTypes.insert(fullName)
}
for objConfig in config.objects {
switch objConfig {
case .object(let name, let overrides):
classOverrides[name] = overrides
case .function(let className, let functionName, let overrides):
let key = "\(className).\(functionName)"
functionOverrides[key] = overrides
case .functionPattern, .signal, .property:
break
}
}
return AnalysisResult(
classHierarchy: classHierarchy,
generatedTypes: generatedTypes,
manualTypes: manualTypes,
ignoredTypes: ignoredTypes,
classOverrides: classOverrides,
functionOverrides: functionOverrides
)
}
}