Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Interface

Mattt edited this page Apr 5, 2020 · 12 revisions
public final class Interface: Codable

Inheritance

Codable

Initializers

init(imports:symbols:)

public required init(imports: [Import], symbols: [Symbol])

Properties

imports

let imports: [Import]

symbols

let symbols: [Symbol]

symbolsGroupedByIdentifier

var symbolsGroupedByIdentifier: [Symbol.ID: [Symbol]] = {
        return Dictionary(grouping: symbols, by: { $0.id })
    }()

symbolsGroupedByQualifiedName

var symbolsGroupedByQualifiedName: [String: [Symbol]] = {
        return Dictionary(grouping: symbols, by: { $0.id.description })
    }()

topLevelSymbols

var topLevelSymbols: [Symbol] = {
        return symbols.filter { $0.api is Type || $0.id.pathComponents.isEmpty }
    }()

baseClasses

var baseClasses: [Symbol] = {
        return symbols.filter { $0.api is Class &&
            typesInherited(by: $0).isEmpty }
    }()

classHierarchies

var classHierarchies: [Symbol: Set<Symbol>] = {
        var classClusters: [Symbol: Set<Symbol>] = [:]

        for baseClass in baseClasses {
            var superclasses = Set(CollectionOfOne(baseClass))

            while !superclasses.isEmpty {
                let subclasses = Set(superclasses.flatMap { typesInheriting(from: $0) }.filter { $0.isPublic })
                defer { superclasses = subclasses }
                classClusters[baseClass, default: []].formUnion(subclasses)
            }
        }

        return classClusters
    }()

relationships

var relationships: [Relationship] = {
        var relationships: Set<Relationship> = []
        for symbol in symbols {
            let `extension` = symbol.context.compactMap({ $0 as? Extension }).first

            if let container = symbol.context.compactMap({ $0 as? Symbol }).last {
                let predicate: Relationship.Predicate

                switch container.api {
                case is Protocol:
                    if symbol.api.modifiers.contains(where: { $0.name == "optional" }) {
                        predicate = .optionalRequirementOf
                    } else {
                        predicate = .requirementOf
                    }
                default:
                    predicate = .memberOf
                }

                relationships.insert(Relationship(subject: symbol, predicate: predicate, object: container))
            }

            if let `extension` = `extension` {
                if let extended = symbols.first(where: { $0.api is Type &&  $0.id.matches(`extension`.extendedType) }) {

                    let predicate: Relationship.Predicate
                    switch extended.api {
                    case is Protocol:
                        predicate = .defaultImplementationOf
                    default:
                        predicate = .memberOf
                    }

                    relationships.insert(Relationship(subject: symbol, predicate: predicate, object: extended))
                }
            }

            if let type = symbol.api as? Type {
                var inheritedTypeNames: Set<String> = []
                inheritedTypeNames.formUnion(type.inheritance.flatMap { $0.split(separator: "&").map { $0.trimmingCharacters(in: .whitespaces) }
                })

                for `extension` in extensionsByExtendedType[symbol.id.description] ?? [] {
                    inheritedTypeNames.formUnion(`extension`.inheritance)
                }

                inheritedTypeNames = Set(inheritedTypeNames.flatMap { $0.split(separator: "&").map { $0.trimmingCharacters(in: .whitespaces) } })

                for name in inheritedTypeNames {
                    let inheritedTypes = symbols.filter({ ($0.api is Class || $0.api is Protocol) && $0.id.description == name })
                    if inheritedTypes.isEmpty {
                        let inherited = Symbol(api: Unknown(name: name), context: [], declaration: nil, documentation: nil, sourceLocation: nil)
                        relationships.insert(Relationship(subject: symbol, predicate: .conformsTo, object: inherited))
                    } else {
                        for inherited in inheritedTypes {
                            let predicate: Relationship.Predicate
                            if symbol.api is Class, inherited.api is Class {
                                predicate = .inheritsFrom
                            } else {
                                predicate = .conformsTo
                            }

                            relationships.insert(Relationship(subject: symbol, predicate: predicate, object: inherited))
                        }
                    }
                }
            }
        }

        return Array(relationships)
    }()

relationshipsBySubject

var relationshipsBySubject: [Symbol.ID: [Relationship]] = {
        Dictionary(grouping: relationships, by: { $0.subject.id })
    }()

relationshipsByObject

var relationshipsByObject: [Symbol.ID: [Relationship]] = {
        Dictionary(grouping: relationships, by: { $0.object.id })
    }()

Methods

members(of:)

public func members(of symbol: Symbol) -> [Symbol]

requirements(of:)

public func requirements(of symbol: Symbol) -> [Symbol]

optionalRequirements(of:)

public func optionalRequirements(of symbol: Symbol) -> [Symbol]

typesInherited(by:)

public func typesInherited(by symbol: Symbol) -> [Symbol]

typesInheriting(from:)

public func typesInheriting(from symbol: Symbol) -> [Symbol]

typesConformed(by:)

public func typesConformed(by symbol: Symbol) -> [Symbol]

typesConforming(to:)

public func typesConforming(to symbol: Symbol) -> [Symbol]

conditionalCounterparts(of:)

public func conditionalCounterparts(of symbol: Symbol) -> [Symbol]
Clone this wiki locally