Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 33f948a
Author: MontakOleg <[email protected]>
Date:   Sat Jun 22 15:38:14 2024 +0300

    AutoMockable: fix generating static reset func (#1336)

    - don't generate invalid code (see
    #1335)
    - use type's access level for generated reset() function

commit 2f8fc64
Author: art-divin <[email protected]>
Date:   Wed Jun 19 18:58:34 2024 +0000

    Update Docs

commit 7153768
Author: Ruslan A <[email protected]>
Date:   Wed Jun 19 22:50:18 2024 +0400

    Fix associatedtype generics (#1345)

    * Preliminary associatedtype support

    * Implemented associatedtype support with generic requirements

    * Fixed failing test

    * Squashed commit of the following:

    commit 9d01e6f
    Author: Ruslan A <[email protected]>
    Date:   Fri Jun 14 20:06:41 2024 +0400

        Improved concurrency support in SwiftTemplate caching (#1344)

    * Removed test code

    * Removed comment

    * Updated Linux classes

    * update internal boilerplate code.

    * Updated generated code

    * Removed warnings

    * Updated expected file

    * Updated expected file

    * Adjusted protocol type for Linux

    * Removed protocol composition due to Swift compiler crash under Linux
  • Loading branch information
art-divin committed Jun 22, 2024
1 parent e95feac commit 5a96740
Show file tree
Hide file tree
Showing 34 changed files with 1,048 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -246,16 +246,37 @@ class SyntaxTreeCollector: SyntaxVisitor {
let name = node.name.text.trimmed
var typeName: TypeName?
var type: Type?

if let possibleTypeName = node.inheritanceClause?.inheritedTypes.description.trimmed {
var genericRequirements: [GenericRequirement] = []
if let genericWhereClause = node.genericWhereClause {
genericRequirements = genericWhereClause.requirements.compactMap { requirement in
if let sameType = requirement.requirement.as(SameTypeRequirementSyntax.self) {
return GenericRequirement(sameType)
} else if let conformanceType = requirement.requirement.as(ConformanceRequirementSyntax.self) {
return GenericRequirement(conformanceType)
}
return nil
}
}
if let composition = processPossibleProtocolComposition(for: possibleTypeName, localName: "") {
type = composition
} else {
type = Protocol(name: possibleTypeName, genericRequirements: genericRequirements)
}
typeName = TypeName(possibleTypeName)
} else if let possibleTypeName = (node.initializer?.value as? TypeSyntax)?.description.trimmed {
type = processPossibleProtocolComposition(for: possibleTypeName, localName: "")
typeName = TypeName(possibleTypeName)
} else {
type = Type(name: "Any")
typeName = TypeName(name: "Any", actualTypeName: TypeName(name: "Any"))
}

sourceryProtocol.associatedTypes[name] = AssociatedType(name: name, typeName: typeName, type: type)
return .skipChildren
}


public override func visit(_ node: OperatorDeclSyntax) -> SyntaxVisitorContinueKind {
return .skipChildren
}
Expand Down
12 changes: 9 additions & 3 deletions SourceryRuntime/Sources/Common/AST/Actor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import Foundation
@objc(SwiftActor) @objcMembers
#endif
public final class Actor: Type {

// sourcery: skipJSExport
public class var kind: String { return "actor" }

/// Returns "actor"
public override var kind: String { return "actor" }
public override var kind: String { Self.kind }

/// Whether type is final
public var isFinal: Bool {
Expand Down Expand Up @@ -36,7 +40,8 @@ public final class Actor: Type {
annotations: [String: NSObject] = [:],
documentation: [String] = [],
isGeneric: Bool = false,
implements: [String: Type] = [:]) {
implements: [String: Type] = [:],
kind: String = Actor.kind) {
super.init(
name: name,
parent: parent,
Expand All @@ -54,7 +59,8 @@ public final class Actor: Type {
annotations: annotations,
documentation: documentation,
isGeneric: isGeneric,
implements: implements
implements: implements,
kind: kind
)
}

Expand Down
11 changes: 8 additions & 3 deletions SourceryRuntime/Sources/Common/AST/Class.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import Foundation
@objc(SwiftClass) @objcMembers
#endif
public final class Class: Type {
// sourcery: skipJSExport
public class var kind: String { return "class" }

/// Returns "class"
public override var kind: String { return "class" }
public override var kind: String { Self.kind }

/// Whether type is final
public var isFinal: Bool {
Expand All @@ -30,7 +33,8 @@ public final class Class: Type {
annotations: [String: NSObject] = [:],
documentation: [String] = [],
isGeneric: Bool = false,
implements: [String: Type] = [:]) {
implements: [String: Type] = [:],
kind: String = Class.kind) {
super.init(
name: name,
parent: parent,
Expand All @@ -48,7 +52,8 @@ public final class Class: Type {
annotations: annotations,
documentation: documentation,
isGeneric: isGeneric,
implements: implements
implements: implements,
kind: kind
)
}

Expand Down
16 changes: 11 additions & 5 deletions SourceryRuntime/Sources/Common/AST/Protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@

import Foundation

#if canImport(ObjectiveC)

/// :nodoc:
public typealias SourceryProtocol = Protocol

/// Describes Swift protocol
#if canImport(ObjectiveC)
@objcMembers
#endif
public final class Protocol: Type {

// sourcery: skipJSExport
public class var kind: String { return "protocol" }

/// Returns "protocol"
public override var kind: String { return "protocol" }
public override var kind: String { Self.kind }

/// list of all declared associated types with their names as keys
public var associatedTypes: [String: AssociatedType] {
Expand Down Expand Up @@ -52,7 +55,8 @@ public final class Protocol: Type {
modifiers: [SourceryModifier] = [],
annotations: [String: NSObject] = [:],
documentation: [String] = [],
implements: [String: Type] = [:]) {
implements: [String: Type] = [:],
kind: String = Protocol.kind) {
self.associatedTypes = associatedTypes
super.init(
name: name,
Expand All @@ -71,7 +75,8 @@ public final class Protocol: Type {
annotations: annotations,
documentation: documentation,
isGeneric: !associatedTypes.isEmpty || !genericRequirements.isEmpty,
implements: implements
implements: implements,
kind: kind
)
}

Expand Down Expand Up @@ -132,3 +137,4 @@ public final class Protocol: Type {
}
// sourcery:end
}
#endif
11 changes: 8 additions & 3 deletions SourceryRuntime/Sources/Common/AST/ProtocolComposition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import Foundation
#endif
public final class ProtocolComposition: Type {

// sourcery: skipJSExport
public class var kind: String { return "protocolComposition" }

/// Returns "protocolComposition"
public override var kind: String { return "protocolComposition" }
public override var kind: String { Self.kind }

/// The names of the types composed to form this composition
public let composedTypeNames: [TypeName]
Expand All @@ -35,7 +38,8 @@ public final class ProtocolComposition: Type {
isGeneric: Bool = false,
composedTypeNames: [TypeName] = [],
composedTypes: [Type]? = nil,
implements: [String: Type] = [:]) {
implements: [String: Type] = [:],
kind: String = ProtocolComposition.kind) {
self.composedTypeNames = composedTypeNames
self.composedTypes = composedTypes
super.init(
Expand All @@ -51,7 +55,8 @@ public final class ProtocolComposition: Type {
typealiases: typealiases,
annotations: annotations,
isGeneric: isGeneric,
implements: implements
implements: implements,
kind: kind
)
}

Expand Down
11 changes: 8 additions & 3 deletions SourceryRuntime/Sources/Common/AST/Struct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import Foundation
#endif
public final class Struct: Type {

// sourcery: skipJSExport
public class var kind: String { return "struct" }

/// Returns "struct"
public override var kind: String { return "struct" }
public override var kind: String { Self.kind }

/// :nodoc:
public override init(name: String = "",
Expand All @@ -35,7 +38,8 @@ public final class Struct: Type {
annotations: [String: NSObject] = [:],
documentation: [String] = [],
isGeneric: Bool = false,
implements: [String: Type] = [:]) {
implements: [String: Type] = [:],
kind: String = Struct.kind) {
super.init(
name: name,
parent: parent,
Expand All @@ -53,7 +57,8 @@ public final class Struct: Type {
annotations: annotations,
documentation: documentation,
isGeneric: isGeneric,
implements: implements
implements: implements,
kind: kind
)
}

Expand Down
12 changes: 7 additions & 5 deletions SourceryRuntime/Sources/Common/Composer/Composer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ public enum Composer {
let composed = ParserResultsComposed(parserResult: parserResult)

let resolveType = { (typeName: TypeName, containingType: Type?) -> Type? in
return composed.resolveType(typeName: typeName, containingType: containingType)
composed.resolveType(typeName: typeName, containingType: containingType)
}

let methodResolveType = { (typeName: TypeName, containingType: Type?, method: Method) -> Type? in
return composed.resolveType(typeName: typeName, containingType: containingType, method: method)
composed.resolveType(typeName: typeName, containingType: containingType, method: method)
}

let processType = { (type: Type) in
Expand All @@ -52,7 +52,7 @@ public enum Composer {
}

if let sourceryProtocol = type as? SourceryProtocol {
resolveProtocolTypes(sourceryProtocol, resolve: resolveType)
resolveAssociatedTypes(sourceryProtocol, resolve: resolveType)
}
}

Expand Down Expand Up @@ -180,11 +180,13 @@ public enum Composer {
protocolComposition.composedTypes = composedTypes
}

private static func resolveProtocolTypes(_ sourceryProtocol: SourceryProtocol, resolve: TypeResolver) {
private static func resolveAssociatedTypes(_ sourceryProtocol: SourceryProtocol, resolve: TypeResolver) {
sourceryProtocol.associatedTypes.forEach { (_, value) in
guard let typeName = value.typeName,
let type = resolve(typeName, sourceryProtocol)
else { return }
else {
return
}
value.type = type
}

Expand Down
54 changes: 43 additions & 11 deletions SourceryRuntime/Sources/Common/Composer/ParserResultsComposed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal struct ParserResultsComposed {
let parsedTypes: [Type]
let functions: [SourceryMethod]
let resolvedTypealiases: [String: Typealias]
let associatedTypes: [String: AssociatedType]
let unresolvedTypealiases: [String: Typealias]

init(parserResult: FileParserResult) {
Expand All @@ -23,6 +24,7 @@ internal struct ParserResultsComposed {
let aliases = Self.typealiases(parserResult)
resolvedTypealiases = aliases.resolved
unresolvedTypealiases = aliases.unresolved
associatedTypes = Self.extractAssociatedTypes(parserResult)
parsedTypes = parserResult.types

// set definedInType for all methods and variables
Expand Down Expand Up @@ -51,6 +53,11 @@ internal struct ParserResultsComposed {
alias.type = resolveType(typeName: alias.typeName, containingType: alias.parent)
}

/// Map associated types
associatedTypes.forEach {
typeMap[$0.key] = $0.value.type
}

types = unifyTypes()
}

Expand Down Expand Up @@ -96,7 +103,7 @@ internal struct ParserResultsComposed {
resolveExtensionOfNestedType(type)
}

if let resolved = resolveGlobalName(for: oldName, containingType: type.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases)?.name {
if let resolved = resolveGlobalName(for: oldName, containingType: type.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases, associatedTypes: associatedTypes)?.name {
var moduleName: String = ""
if let module = type.module {
moduleName = "\(module)."
Expand All @@ -116,7 +123,7 @@ internal struct ParserResultsComposed {
// extend all types with their extensions
parsedTypes.forEach { type in
let inheritedTypes: [[String]] = type.inheritedTypes.compactMap { inheritedName in
if let resolvedGlobalName = resolveGlobalName(for: inheritedName, containingType: type.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases)?.name {
if let resolvedGlobalName = resolveGlobalName(for: inheritedName, containingType: type.parent, unique: typeMap, modules: modules, typealiases: resolvedTypealiases, associatedTypes: associatedTypes)?.name {
return [resolvedGlobalName]
}
if let baseType = Composer.findBaseType(for: type, name: inheritedName, typesByName: typeMap) {
Expand Down Expand Up @@ -175,6 +182,14 @@ internal struct ParserResultsComposed {
})
}

// extract associated types from all types and add them to types
private static func extractAssociatedTypes(_ parserResult: FileParserResult) -> [String: AssociatedType] {
parserResult.types
.compactMap { $0 as? SourceryProtocol }
.map { $0.associatedTypes }
.flatMap { $0 }.reduce(into: [:]) { $0[$1.key] = $1.value }
}

/// returns typealiases map to their full names, with `resolved` removing intermediate
/// typealises and `unresolved` including typealiases that reference other typealiases.
private static func typealiases(_ parserResult: FileParserResult) -> (resolved: [String: Typealias], unresolved: [String: Typealias]) {
Expand Down Expand Up @@ -207,11 +222,14 @@ internal struct ParserResultsComposed {
}

/// Resolves type identifier for name
func resolveGlobalName(for type: String,
containingType: Type? = nil,
unique: [String: Type]? = nil,
modules: [String: [String: Type]],
typealiases: [String: Typealias]) -> (name: String, typealias: Typealias?)? {
func resolveGlobalName(
for type: String,
containingType: Type? = nil,
unique: [String: Type]? = nil,
modules: [String: [String: Type]],
typealiases: [String: Typealias],
associatedTypes: [String: AssociatedType]
) -> (name: String, typealias: Typealias?)? {
// if the type exists for this name and isn't an extension just return it's name
// if it's extension we need to check if there aren't other options TODO: verify
if let realType = unique?[type], realType.isExtension == false {
Expand All @@ -222,6 +240,13 @@ internal struct ParserResultsComposed {
return (name: alias.type?.globalName ?? alias.typeName.name, typealias: alias)
}

if let associatedType = associatedTypes[type],
let actualType = associatedType.type
{
let typeName = associatedType.typeName ?? TypeName(name: actualType.name)
return (name: actualType.globalName, typealias: Typealias(aliasName: type, typeName: typeName))
}

if let containingType = containingType {
if type == "Self" {
return (name: containingType.globalName, typealias: nil)
Expand All @@ -231,7 +256,7 @@ internal struct ParserResultsComposed {
while currentContainer != nil, let parentName = currentContainer?.globalName {
/// TODO: no parent for sure?
/// manually walk the containment tree
if let name = resolveGlobalName(for: "\(parentName).\(type)", containingType: nil, unique: unique, modules: modules, typealiases: typealiases) {
if let name = resolveGlobalName(for: "\(parentName).\(type)", containingType: nil, unique: unique, modules: modules, typealiases: typealiases, associatedTypes: associatedTypes) {
return name
}

Expand Down Expand Up @@ -565,20 +590,27 @@ internal struct ParserResultsComposed {
}
}

return unique[resolvedIdentifier]
if let associatedType = associatedTypes[resolvedIdentifier] {
return associatedType.type
}

return unique[resolvedIdentifier] ?? unique[typeName.name]
}

private func actualTypeName(for typeName: TypeName,
containingType: Type? = nil) -> TypeName? {
containingType: Type? = nil) -> TypeName? {
let unique = typeMap
let typealiases = resolvedTypealiases
let associatedTypes = associatedTypes

var unwrapped = typeName.unwrappedTypeName
if let generic = typeName.generic {
unwrapped = generic.name
} else if let type = associatedTypes[unwrapped] {
unwrapped = type.name
}

guard let aliased = resolveGlobalName(for: unwrapped, containingType: containingType, unique: unique, modules: modules, typealiases: typealiases) else {
guard let aliased = resolveGlobalName(for: unwrapped, containingType: containingType, unique: unique, modules: modules, typealiases: typealiases, associatedTypes: associatedTypes) else {
return nil
}

Expand Down
Loading

0 comments on commit 5a96740

Please sign in to comment.