Files
Sourcery/SourceryRuntime/Sources/Linux/AST/Method_Linux.swift
T
Ruslan A 7153768c65 Fix associatedtype generics (#1345)
* Preliminary associatedtype support

* Implemented associatedtype support with generic requirements

* Fixed failing test

* Squashed commit of the following:

commit 9d01e6f99a
Author: Ruslan A <r.alikhamov@gmail.com>
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
2024-06-19 22:50:18 +04:00

480 lines
23 KiB
Swift

#if !canImport(ObjectiveC)
import Foundation
/// :nodoc:
public typealias SourceryMethod = Method
/// Describes method
public final class Method: NSObject, SourceryModel, Annotated, Documented, Definition, Diffable, SourceryDynamicMemberLookup {
public subscript(dynamicMember member: String) -> Any? {
switch member {
case "definedInType":
return definedInType
case "shortName":
return shortName
case "name":
return name
case "selectorName":
return selectorName
case "callName":
return callName
case "parameters":
return parameters
case "throws":
return `throws`
case "isInitializer":
return isInitializer
case "accessLevel":
return accessLevel
case "isStatic":
return isStatic
case "returnTypeName":
return returnTypeName
case "isAsync":
return isAsync
case "attributes":
return attributes
case "isOptionalReturnType":
return isOptionalReturnType
case "actualReturnTypeName":
return actualReturnTypeName
case "isDynamic":
return isDynamic
case "genericRequirements":
return genericRequirements
default:
fatalError("unable to lookup: \(member) in \(self)")
}
}
/// Full method name, including generic constraints, i.e. `foo<T>(bar: T)`
public let name: String
/// Method name including arguments names, i.e. `foo(bar:)`
public var selectorName: String
// sourcery: skipEquality, skipDescription
/// Method name without arguments names and parentheses, i.e. `foo<T>`
public var shortName: String {
return name.range(of: "(").map({ String(name[..<$0.lowerBound]) }) ?? name
}
// sourcery: skipEquality, skipDescription
/// Method name without arguments names, parentheses and generic types, i.e. `foo` (can be used to generate code for method call)
public var callName: String {
return shortName.range(of: "<").map({ String(shortName[..<$0.lowerBound]) }) ?? shortName
}
/// Method parameters
public var parameters: [MethodParameter]
/// Return value type name used in declaration, including generic constraints, i.e. `where T: Equatable`
public var returnTypeName: TypeName
// sourcery: skipEquality, skipDescription
/// Actual return value type name if declaration uses typealias, otherwise just a `returnTypeName`
public var actualReturnTypeName: TypeName {
return returnTypeName.actualTypeName ?? returnTypeName
}
// sourcery: skipEquality, skipDescription
/// Actual return value type, if known
public var returnType: Type?
// sourcery: skipEquality, skipDescription
/// Whether return value type is optional
public var isOptionalReturnType: Bool {
return returnTypeName.isOptional || isFailableInitializer
}
// sourcery: skipEquality, skipDescription
/// Whether return value type is implicitly unwrapped optional
public var isImplicitlyUnwrappedOptionalReturnType: Bool {
return returnTypeName.isImplicitlyUnwrappedOptional
}
// sourcery: skipEquality, skipDescription
/// Return value type name without attributes and optional type information
public var unwrappedReturnTypeName: String {
return returnTypeName.unwrappedTypeName
}
/// Whether method is async method
public let isAsync: Bool
/// Whether method is distributed
public var isDistributed: Bool {
modifiers.contains(where: { $0.name == "distributed" })
}
/// Whether method throws
public let `throws`: Bool
/// Whether method rethrows
public let `rethrows`: Bool
/// Method access level, i.e. `internal`, `private`, `fileprivate`, `public`, `open`
public let accessLevel: String
/// Whether method is a static method
public let isStatic: Bool
/// Whether method is a class method
public let isClass: Bool
// sourcery: skipEquality, skipDescription
/// Whether method is an initializer
public var isInitializer: Bool {
return selectorName.hasPrefix("init(") || selectorName == "init"
}
// sourcery: skipEquality, skipDescription
/// Whether method is an deinitializer
public var isDeinitializer: Bool {
return selectorName == "deinit"
}
/// Whether method is a failable initializer
public let isFailableInitializer: Bool
// sourcery: skipEquality, skipDescription
/// Whether method is a convenience initializer
public var isConvenienceInitializer: Bool {
modifiers.contains { $0.name == Attribute.Identifier.convenience.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is required
public var isRequired: Bool {
modifiers.contains { $0.name == Attribute.Identifier.required.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is final
public var isFinal: Bool {
modifiers.contains { $0.name == Attribute.Identifier.final.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is mutating
public var isMutating: Bool {
modifiers.contains { $0.name == Attribute.Identifier.mutating.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is generic
public var isGeneric: Bool {
shortName.hasSuffix(">")
}
// sourcery: skipEquality, skipDescription
/// Whether method is optional (in an Objective-C protocol)
public var isOptional: Bool {
modifiers.contains { $0.name == Attribute.Identifier.optional.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is nonisolated (this modifier only applies to actor methods)
public var isNonisolated: Bool {
modifiers.contains { $0.name == Attribute.Identifier.nonisolated.rawValue }
}
// sourcery: skipEquality, skipDescription
/// Whether method is dynamic
public var isDynamic: Bool {
modifiers.contains { $0.name == Attribute.Identifier.dynamic.rawValue }
}
/// Annotations, that were created with // sourcery: annotation1, other = "annotation value", alterantive = 2
public let annotations: Annotations
public let documentation: Documentation
/// Reference to type name where the method is defined,
/// nil if defined outside of any `enum`, `struct`, `class` etc
public let definedInTypeName: TypeName?
// sourcery: skipEquality, skipDescription
/// Reference to actual type name where the method is defined if declaration uses typealias, otherwise just a `definedInTypeName`
public var actualDefinedInTypeName: TypeName? {
return definedInTypeName?.actualTypeName ?? definedInTypeName
}
// sourcery: skipEquality, skipDescription
/// Reference to actual type where the object is defined,
/// nil if defined outside of any `enum`, `struct`, `class` etc or type is unknown
public var definedInType: Type?
/// Method attributes, i.e. `@discardableResult`
public let attributes: AttributeList
/// Method modifiers, i.e. `private`
public let modifiers: [SourceryModifier]
// Underlying parser data, never to be used by anything else
// sourcery: skipEquality, skipDescription, skipCoding, skipJSExport
/// :nodoc:
public var __parserData: Any?
/// list of generic requirements
public var genericRequirements: [GenericRequirement]
/// List of generic parameters
///
/// - Example:
///
/// ```swift
/// func method<GenericParameter>(foo: GenericParameter)
/// ^ ~ a generic parameter
/// ```
public var genericParameters: [GenericParameter]
/// :nodoc:
public init(name: String,
selectorName: String? = nil,
parameters: [MethodParameter] = [],
returnTypeName: TypeName = TypeName(name: "Void"),
isAsync: Bool = false,
throws: Bool = false,
rethrows: Bool = false,
accessLevel: AccessLevel = .internal,
isStatic: Bool = false,
isClass: Bool = false,
isFailableInitializer: Bool = false,
attributes: AttributeList = [:],
modifiers: [SourceryModifier] = [],
annotations: [String: NSObject] = [:],
documentation: [String] = [],
definedInTypeName: TypeName? = nil,
genericRequirements: [GenericRequirement] = [],
genericParameters: [GenericParameter] = []) {
self.name = name
self.selectorName = selectorName ?? name
self.parameters = parameters
self.returnTypeName = returnTypeName
self.isAsync = isAsync
self.throws = `throws`
self.rethrows = `rethrows`
self.accessLevel = accessLevel.rawValue
self.isStatic = isStatic
self.isClass = isClass
self.isFailableInitializer = isFailableInitializer
self.attributes = attributes
self.modifiers = modifiers
self.annotations = annotations
self.documentation = documentation
self.definedInTypeName = definedInTypeName
self.genericRequirements = genericRequirements
self.genericParameters = genericParameters
}
/// :nodoc:
// sourcery: skipJSExport
override public var description: String {
var string = "\(Swift.type(of: self)): "
string.append("name = \(String(describing: self.name)), ")
string.append("selectorName = \(String(describing: self.selectorName)), ")
string.append("parameters = \(String(describing: self.parameters)), ")
string.append("returnTypeName = \(String(describing: self.returnTypeName)), ")
string.append("isAsync = \(String(describing: self.isAsync)), ")
string.append("`throws` = \(String(describing: self.`throws`)), ")
string.append("`rethrows` = \(String(describing: self.`rethrows`)), ")
string.append("accessLevel = \(String(describing: self.accessLevel)), ")
string.append("isStatic = \(String(describing: self.isStatic)), ")
string.append("isClass = \(String(describing: self.isClass)), ")
string.append("isFailableInitializer = \(String(describing: self.isFailableInitializer)), ")
string.append("annotations = \(String(describing: self.annotations)), ")
string.append("documentation = \(String(describing: self.documentation)), ")
string.append("definedInTypeName = \(String(describing: self.definedInTypeName)), ")
string.append("attributes = \(String(describing: self.attributes)), ")
string.append("modifiers = \(String(describing: self.modifiers)), ")
string.append("genericRequirements = \(String(describing: self.genericRequirements)), ")
string.append("genericRequirements = \(String(describing: self.genericParameters))")
return string
}
public func diffAgainst(_ object: Any?) -> DiffableResult {
let results = DiffableResult()
guard let castObject = object as? Method else {
results.append("Incorrect type <expected: Method, received: \(Swift.type(of: object))>")
return results
}
results.append(contentsOf: DiffableResult(identifier: "name").trackDifference(actual: self.name, expected: castObject.name))
results.append(contentsOf: DiffableResult(identifier: "selectorName").trackDifference(actual: self.selectorName, expected: castObject.selectorName))
results.append(contentsOf: DiffableResult(identifier: "parameters").trackDifference(actual: self.parameters, expected: castObject.parameters))
results.append(contentsOf: DiffableResult(identifier: "returnTypeName").trackDifference(actual: self.returnTypeName, expected: castObject.returnTypeName))
results.append(contentsOf: DiffableResult(identifier: "isAsync").trackDifference(actual: self.isAsync, expected: castObject.isAsync))
results.append(contentsOf: DiffableResult(identifier: "`throws`").trackDifference(actual: self.`throws`, expected: castObject.`throws`))
results.append(contentsOf: DiffableResult(identifier: "`rethrows`").trackDifference(actual: self.`rethrows`, expected: castObject.`rethrows`))
results.append(contentsOf: DiffableResult(identifier: "accessLevel").trackDifference(actual: self.accessLevel, expected: castObject.accessLevel))
results.append(contentsOf: DiffableResult(identifier: "isStatic").trackDifference(actual: self.isStatic, expected: castObject.isStatic))
results.append(contentsOf: DiffableResult(identifier: "isClass").trackDifference(actual: self.isClass, expected: castObject.isClass))
results.append(contentsOf: DiffableResult(identifier: "isFailableInitializer").trackDifference(actual: self.isFailableInitializer, expected: castObject.isFailableInitializer))
results.append(contentsOf: DiffableResult(identifier: "annotations").trackDifference(actual: self.annotations, expected: castObject.annotations))
results.append(contentsOf: DiffableResult(identifier: "documentation").trackDifference(actual: self.documentation, expected: castObject.documentation))
results.append(contentsOf: DiffableResult(identifier: "definedInTypeName").trackDifference(actual: self.definedInTypeName, expected: castObject.definedInTypeName))
results.append(contentsOf: DiffableResult(identifier: "attributes").trackDifference(actual: self.attributes, expected: castObject.attributes))
results.append(contentsOf: DiffableResult(identifier: "modifiers").trackDifference(actual: self.modifiers, expected: castObject.modifiers))
results.append(contentsOf: DiffableResult(identifier: "genericRequirements").trackDifference(actual: self.genericRequirements, expected: castObject.genericRequirements))
results.append(contentsOf: DiffableResult(identifier: "genericParameters").trackDifference(actual: self.genericParameters, expected: castObject.genericParameters))
return results
}
/// :nodoc:
// sourcery: skipJSExport
public override var hash: Int {
var hasher = Hasher()
hasher.combine(self.name)
hasher.combine(self.selectorName)
hasher.combine(self.parameters)
hasher.combine(self.returnTypeName)
hasher.combine(self.isAsync)
hasher.combine(self.`throws`)
hasher.combine(self.`rethrows`)
hasher.combine(self.accessLevel)
hasher.combine(self.isStatic)
hasher.combine(self.isClass)
hasher.combine(self.isFailableInitializer)
hasher.combine(self.annotations)
hasher.combine(self.documentation)
hasher.combine(self.definedInTypeName)
hasher.combine(self.attributes)
hasher.combine(self.modifiers)
hasher.combine(self.genericRequirements)
hasher.combine(self.genericParameters)
return hasher.finalize()
}
/// :nodoc:
public override func isEqual(_ object: Any?) -> Bool {
guard let rhs = object as? Method else { return false }
if self.name != rhs.name { return false }
if self.selectorName != rhs.selectorName { return false }
if self.parameters != rhs.parameters { return false }
if self.returnTypeName != rhs.returnTypeName { return false }
if self.isAsync != rhs.isAsync { return false }
if self.isDistributed != rhs.isDistributed { return false }
if self.`throws` != rhs.`throws` { return false }
if self.`rethrows` != rhs.`rethrows` { return false }
if self.accessLevel != rhs.accessLevel { return false }
if self.isStatic != rhs.isStatic { return false }
if self.isClass != rhs.isClass { return false }
if self.isFailableInitializer != rhs.isFailableInitializer { return false }
if self.annotations != rhs.annotations { return false }
if self.documentation != rhs.documentation { return false }
if self.definedInTypeName != rhs.definedInTypeName { return false }
if self.attributes != rhs.attributes { return false }
if self.modifiers != rhs.modifiers { return false }
if self.genericRequirements != rhs.genericRequirements { return false }
if self.genericParameters != rhs.genericParameters { return false }
return true
}
// sourcery:inline:Method.AutoCoding
/// :nodoc:
required public init?(coder aDecoder: NSCoder) {
guard let name: String = aDecoder.decode(forKey: "name") else {
withVaList(["name"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.name = name
guard let selectorName: String = aDecoder.decode(forKey: "selectorName") else {
withVaList(["selectorName"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.selectorName = selectorName
guard let parameters: [MethodParameter] = aDecoder.decode(forKey: "parameters") else {
withVaList(["parameters"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.parameters = parameters
guard let returnTypeName: TypeName = aDecoder.decode(forKey: "returnTypeName") else {
withVaList(["returnTypeName"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.returnTypeName = returnTypeName
self.returnType = aDecoder.decode(forKey: "returnType")
self.isAsync = aDecoder.decode(forKey: "isAsync")
self.`throws` = aDecoder.decode(forKey: "`throws`")
self.`rethrows` = aDecoder.decode(forKey: "`rethrows`")
guard let accessLevel: String = aDecoder.decode(forKey: "accessLevel") else {
withVaList(["accessLevel"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.accessLevel = accessLevel
self.isStatic = aDecoder.decode(forKey: "isStatic")
self.isClass = aDecoder.decode(forKey: "isClass")
self.isFailableInitializer = aDecoder.decode(forKey: "isFailableInitializer")
guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else {
withVaList(["annotations"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.annotations = annotations
guard let documentation: Documentation = aDecoder.decode(forKey: "documentation") else {
withVaList(["documentation"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.documentation = documentation
self.definedInTypeName = aDecoder.decode(forKey: "definedInTypeName")
self.definedInType = aDecoder.decode(forKey: "definedInType")
guard let attributes: AttributeList = aDecoder.decode(forKey: "attributes") else {
withVaList(["attributes"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.attributes = attributes
guard let modifiers: [SourceryModifier] = aDecoder.decode(forKey: "modifiers") else {
withVaList(["modifiers"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.modifiers = modifiers
guard let genericRequirements: [GenericRequirement] = aDecoder.decode(forKey: "genericRequirements") else {
withVaList(["genericRequirements"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.genericRequirements = genericRequirements
guard let genericParameters: [GenericParameter] = aDecoder.decode(forKey: "genericParameters") else {
withVaList(["genericParameters"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.genericParameters = genericParameters
}
/// :nodoc:
public func encode(with aCoder: NSCoder) {
aCoder.encode(self.name, forKey: "name")
aCoder.encode(self.selectorName, forKey: "selectorName")
aCoder.encode(self.parameters, forKey: "parameters")
aCoder.encode(self.returnTypeName, forKey: "returnTypeName")
aCoder.encode(self.returnType, forKey: "returnType")
aCoder.encode(self.isAsync, forKey: "isAsync")
aCoder.encode(self.`throws`, forKey: "`throws`")
aCoder.encode(self.`rethrows`, forKey: "`rethrows`")
aCoder.encode(self.accessLevel, forKey: "accessLevel")
aCoder.encode(self.isStatic, forKey: "isStatic")
aCoder.encode(self.isClass, forKey: "isClass")
aCoder.encode(self.isFailableInitializer, forKey: "isFailableInitializer")
aCoder.encode(self.annotations, forKey: "annotations")
aCoder.encode(self.documentation, forKey: "documentation")
aCoder.encode(self.definedInTypeName, forKey: "definedInTypeName")
aCoder.encode(self.definedInType, forKey: "definedInType")
aCoder.encode(self.attributes, forKey: "attributes")
aCoder.encode(self.modifiers, forKey: "modifiers")
aCoder.encode(self.genericRequirements, forKey: "genericRequirements")
aCoder.encode(self.genericParameters, forKey: "genericParameters")
}
// sourcery:end
}
#endif