How to use specializeTypeName method of without class

Best Mockingbird code snippet using without.specializeTypeName

MockableTypeTemplate.swift

Source:MockableTypeTemplate.swift Github

copy

Full Screen

...69      directiveStart,70      NominalTypeDefinitionTemplate(71        declaration: "public final class \(mockableType.name)Mock",72        genericTypes: genericTypes,73        genericConstraints: mockableType.whereClauses.sorted().map({ specializeTypeName("\($0)") }),74        inheritedTypes: (isAvailable ? inheritedTypes : []) + [Constants.mockProtocolName],75        body: renderBody()).render(),76      directiveEnd,77    ])78  }79  80  lazy var compilationDirectiveDeclaration: (start: String, end: String) = {81    guard !mockableType.compilationDirectives.isEmpty else { return ("", "") }82    let start = String(lines: mockableType.compilationDirectives.map({ $0.declaration }))83    let end = String(lines: mockableType.compilationDirectives.map({ _ in "#endif" }))84    return (start, end)85  }()86  87  lazy var shouldGenerateThunks: Bool = {88    guard let typeNames = mockedTypeNames else { return true }89    return mockableType.isReferenced(by: typeNames)90  }()91  92  lazy var isAvailable: Bool = {93    return unavailableMockAttribute.isEmpty94  }()95  96  /// Protocols that inherit from opaque external types are considered not available as mocks97  /// because it's not possible to generate a well-formed concrete implementation unless the98  /// inheritance is trivial.99  var nonMockableOpaqueInheritanceMessage: String? {100    let hasCompleteInheritance = mockableType.kind != .protocol101      || mockableType.opaqueInheritedTypeNames.isEmpty102    guard !hasCompleteInheritance else { return nil }103    104    let opaqueTypeNames = mockableType.opaqueInheritedTypeNames.sorted()105    let allOpaqueTypeNames = opaqueTypeNames.enumerated().map({ (index, typeName) -> String in106      (index > 0 && index == opaqueTypeNames.count-1 ? "and " : "") + typeName.singleQuoted107    }).joined(separator: opaqueTypeNames.count > 2 ? ", " : " ")108    109    if opaqueTypeNames.count > 1 {110      return "\(mockableType.name.singleQuoted) inherits from the externally-defined types \(allOpaqueTypeNames) which needs to be declared in a supporting source file"111    } else {112      return "\(mockableType.name.singleQuoted) inherits from the externally-defined type \(allOpaqueTypeNames) which needs to be declared in a supporting source file"113    }114  }115  116  /// Cannot mock a type that inherits a type that isn't declared in the same module and isn't open.117  /// This mainly applies to protocols that have a Self constraint to a non-inheritable type.118  var nonMockableInheritedTypeMessage: String? {119    guard let nonInheritableType = mockableType.inheritedTypes120      .union(mockableType.selfConformanceTypes)121      .first(where: {122        $0.kind == .class && !$0.accessLevel.isInheritableType(withinSameModule: $0.shouldMock)123      })124      else { return nil }125    return "\(mockableType.name.singleQuoted) inherits from the non-open class \(nonInheritableType.name.singleQuoted) and cannot be mocked"126  }127  128  /// Protocols can inherit properties whose names conflict from other protocols, such that it is129  /// not possible to create a class that conforms to the child protocol.130  var nonMockablePropertiesMessage: String? {131    let duplicates = Dictionary(grouping: mockableType.variables, by: {Variable.Reduced(from: $0)})132      .mapValues({ $0.count })133      .filter({ $1 > 1 })134    guard !duplicates.isEmpty else { return nil }135    136    let allDuplicates = duplicates.keys137      .sorted(by: { $0.name < $1.name })138      .enumerated()139      .map({ (index, variable) -> String in140        (index > 0 && index == duplicates.count-1 ? "and " : "") + variable.name.singleQuoted141      })142      .joined(separator: duplicates.count > 2 ? ", " : " ")143    144    if duplicates.count > 1 {145      return "\(mockableType.name.singleQuoted) contains the properties \(allDuplicates) that each conflict with inherited declarations and cannot be mocked"146    } else {147      return "\(mockableType.name.singleQuoted) contains the property \(allDuplicates) that conflicts with an inherited declaration and cannot be mocked"148    }149  }150  151  /// Classes that define designated initializers but none which are accessible.152  var nonMockableDesignatedInitializerMessage: String? {153    guard mockableType.kind == .class, !shouldGenerateDefaultInitializer else { return nil }154    guard !mockableType.methods.contains(where: { $0.isDesignatedInitializer && $0.isMockable })155      else { return nil }156    return "\(mockableType.name.singleQuoted) does not declare any accessible designated initializers and cannot be mocked"157  }158  159  /// Classes that cannot be initialized due to imported accessibility from an external module.160  var nonMockableExternalInitializerMessage: String? {161    guard mockableType.kind == .class, mockableType.subclassesExternalType else { return nil }162    guard !mockableType.methods.contains(where: { $0.isInitializer && $0.isMockable })163      else { return nil }164    return "\(mockableType.name.singleQuoted) subclasses a type from a different module but does not declare any accessible initializers and cannot be mocked"165  }166  167  lazy var unavailableMockAttribute: String = {168    guard let message = nonMockableOpaqueInheritanceMessage169      ?? nonMockableInheritedTypeMessage170      ?? nonMockablePropertiesMessage171      ?? nonMockableDesignatedInitializerMessage172      ?? nonMockableExternalInitializerMessage173      else { return "" }174    175    logWarning(176      message,177      diagnostic: .notMockable,178      filePath: mockableType.filePath,179      line: self.mockableType.lineNumber180    )181    182    return """183    @available(*, unavailable, message: "\(message)")184    """185  }()186  187  /// The static mocking context allows static or class methods to be mocked.188  var staticMockingContext: String {189    if !mockableType.genericTypes.isEmpty || mockableType.isInGenericContainingType {190      // Class-level generic types don't support static variables directly.191      let body = !shouldGenerateThunks ? Constants.thunkStub :192        "return genericStaticMockContext.resolveTypeNames([\(runtimeGenericTypeNames)])"193      return """194      static var staticMock: Mockingbird.StaticMock \(BlockTemplate(body: body, multiline: false))195      """196    } else {197      return "static let staticMock = Mockingbird.StaticMock()"198    }199  }200  201  lazy var runtimeGenericTypeNames: String = {202    let baseTypeName = "\(mockableType.name)Mock\(allGenericTypes)"203    let genericTypeSelfNames = mockableType.genericTypes204      .sorted(by: { $0.name < $1.name })205      .map({ "Swift.ObjectIdentifier(\($0.name).self).debugDescription" })206    return String(list: [baseTypeName.doubleQuoted] + genericTypeSelfNames)207  }()208  209  lazy var genericTypes: [String] = {210    return mockableType.genericTypes.map({ $0.flattenedDeclaration })211  }()212  213  lazy var allGenericTypes: String = {214    guard !mockableType.genericTypes.isEmpty else { return "" }215    return "<\(separated: mockableType.genericTypes.map({ $0.name }))>"216  }()217  218  var allInheritedTypes: String {219    return String(list: inheritedTypes + [Constants.mockProtocolName])220  }221  222  /// For scoped types referenced within their containing type.223  lazy var fullyQualifiedName: String = {224    guard mockableType.kind == .class, mockableType.isContainedType else {225      return mockableType.fullyQualifiedModuleName226    }227    return "\(mockableType.name)\(allGenericTypes)"228  }()229  230  /// For scoped types referenced at the top level but in the same module.231  func createScopedName(with containingTypeNames: [String],232                        genericTypeContext: [[String]],233                        suffix: String = "",234                        moduleQualified: Bool = false) -> String {235    let name = moduleQualified ?236      mockableType.fullyQualifiedModuleName.removingGenericTyping() : mockableType.name237    guard mockableType.kind == .class else { // Protocols can't be nested238      return name + suffix + (!suffix.isEmpty ? allGenericTypes : "")239    }240    guard mockableType.isContainedType else {241      return name + suffix + allGenericTypes242    }243    244    let typeNames = containingTypeNames.enumerated()245      .map({ (index, typeName) -> String in246        guard let genericTypeNames = genericTypeContext.get(index), !genericTypeNames.isEmpty else {247          return typeName + suffix248        }249        // Disambiguate generic types that shadow those defined by a containing type.250        return typeName + suffix + "<\(separated: genericTypeNames.map({ typeName + "_" + $0 }))>"251      })252      + [mockableType.name + suffix + allGenericTypes]253    254    if moduleQualified && mockableType.fullyQualifiedName != mockableType.fullyQualifiedModuleName {255      return String(list: [mockableType.moduleName] + typeNames, separator: ".")256    } else {257      return String(list: typeNames, separator: ".")258    }259  }260  261  lazy var protocolClassConformance: String? = {262    guard mockableType.kind == .protocol,263      let classConformance = mockableType.primarySelfConformanceTypeName264      else { return nil }265    266    // Handle class conformance constraints from where clauses.267    return classConformance268  }()269  270  var inheritedTypes: [String] {271    var types = [String]()272    if let protocolClassConformance = self.protocolClassConformance {273      types.append(protocolClassConformance)274    }275    types.append(fullyQualifiedName)276    277    let classConformanceTypeNames = Set(278      mockableType.selfConformanceTypes279        .filter({ $0.kind == .class })280        .map({ $0.fullyQualifiedModuleName })281    )282    let conformanceTypes = Set(mockableType.allSelfConformanceTypeNames)283      .subtracting(classConformanceTypeNames)284      .subtracting(types)285      .sorted()286    return types + conformanceTypes287  }288  289  func renderBody() -> String {290    let supertypeDeclaration = "typealias MockingbirdSupertype = \(fullyQualifiedName)"291    let mockingbirdContext = """292    public let mockingbirdContext = Mockingbird.Context(["generator_version": "\(mockingbirdVersion.shortString)", "module_name": "\(mockableType.moduleName)"])293    """294    295    var components = [String(lines: [296      // Type declarations297      supertypeDeclaration,298      299      // Properties300      staticMockingContext,301      mockingbirdContext,302    ])]303    304    if isAvailable {305      components.append(contentsOf: [306        renderInitializerProxy(),307        renderVariables(),308        defaultInitializer,309        renderMethods(),310        renderContainedTypes()311      ])312    } else {313      components.append(renderContainedTypes())314    }315    316    return String(lines: components, spacing: 2)317  }318  319  func renderContainedTypes() -> String {320    guard !mockableType.containedTypes.isEmpty else { return "" }321    let containedTypesSubstructure = mockableType.containedTypes322      .map({323        MockableTypeTemplate(mockableType: $0, mockedTypeNames: mockedTypeNames)324          .render().indent()325      })326    return String(lines: containedTypesSubstructure, spacing: 2)327  }328  329  func renderInitializerProxy() -> String {330    let isProxyable: (Method) -> Bool = {331      // This needs to be a designated initializer since if it's a convenience initializer, we can't332      // always infer what concrete argument values to pass to the designated initializer.333      $0.isDesignatedInitializer && $0.isMockable334    }335    336    guard !shouldGenerateDefaultInitializer else { return "" }337    let initializers = mockableType.methods338      .filter(isProxyable)339      .filter(isOverridable)340      .sorted()341      .compactMap({ methodTemplate(for: $0).classInitializerProxy })342    343    guard !initializers.isEmpty else {344      return "public enum InitializerProxy {}"345    }346    return NominalTypeDefinitionTemplate(declaration: "public enum InitializerProxy",347                                         body: String(lines: initializers, spacing: 2)).render()348  }349  350  /// Store the source location of where the mock was initialized. This allows `XCTest` errors from351  /// unstubbed method invocations to show up in the testing code.352  var shouldGenerateDefaultInitializer: Bool {353    // Opaque types can have designated initializers we don't know about, so it's best to ignore.354    guard mockableType.opaqueInheritedTypeNames.isEmpty else {355      logWarning(356        "Unable to synthesize default initializer for \(mockableType.name.singleQuoted) which inherits from an external type not defined in a supporting source file",357        diagnostic: .undefinedType,358        filePath: mockableType.filePath,359        line: self.mockableType.lineNumber360      )361      return false362    }363    364    let hasDesignatedInitializer =365      mockableType.methods.contains(where: { $0.isDesignatedInitializer })366    367    guard mockableType.kind == .protocol else { // Handle classes.368      if hasDesignatedInitializer {369        log("Skipping default initializer generation for \(mockableType.name.singleQuoted) because it is a class with a designated initializer")370      }371      return !hasDesignatedInitializer372    }373    374    // We can always generate a default initializer for protocols without class conformance.375    guard protocolClassConformance != nil else { return true }376    377    // Ignore protocols conforming to a class with a designated initializer.378    guard !hasDesignatedInitializer else {379      log("Skipping default initializer generation for \(mockableType.name.singleQuoted) because it is a protocol conforming to a class with a designated initializer")380      return false381    }382    383    let isMockableClassConformance = mockableType.primarySelfConformanceType?.shouldMock ?? true384    if !isMockableClassConformance {385      logWarning(386        "\(mockableType.name.singleQuoted) conforms to a class without public initializers and cannot be initialized",387        diagnostic: .notMockable,388        filePath: mockableType.filePath,389        line: self.mockableType.lineNumber390      )391    }392    return isMockableClassConformance393  }394  395  var defaultInitializer: String {396    guard shouldGenerateDefaultInitializer else { return "" }397    let canCallSuper = mockableType.kind == .class || protocolClassConformance != nil398    return FunctionDefinitionTemplate(399      declaration: "fileprivate init(sourceLocation: Mockingbird.SourceLocation)",400      body: String(lines: [401        canCallSuper ? "super.init()" : "",402        "self.mockingbirdContext.sourceLocation = sourceLocation",403        "\(mockableType.name)Mock.staticMock.mockingbirdContext.sourceLocation = sourceLocation",404      ])).render()405  }406  407  lazy var containsOverridableDesignatedInitializer: Bool = {408    return mockableType.methods.contains(where: {409      $0.isOverridable && $0.isDesignatedInitializer && $0.isMockable410    })411  }()412  413  func renderVariables() -> String {414    return String(lines: mockableType.variables.sorted(by: <).map({415      VariableTemplate(variable: $0, context: self).render()416    }), spacing: 2)417  }418  419  func isOverridable(method: Method) -> Bool {420    let isClassMock = mockableType.kind == .class || mockableType.primarySelfConformanceType != nil421    let isGeneric = !method.whereClauses.isEmpty || !method.genericTypes.isEmpty422    guard isClassMock, isGeneric else { return true }423    424    // Not possible to override overloaded methods where uniqueness is from generic constraints.425    // https://forums.swift.org/t/cannot-override-more-than-one-superclass-declaration/22213426    // This is fixed in Swift 5.2, so non-overridable methods require compilation conditions.427    return mockableType.methodsCount[Method.Reduced(from: method)] == 1428  }429  430  func renderMethods() -> String {431    return String(lines: Set(mockableType.methods).sorted(by: <).filter({ $0.isMockable }).map({432      let renderedMethod = methodTemplate(for: $0).render()433      guard !isOverridable(method: $0) else { return renderedMethod }434      return String(lines: [435        "#if swift(>=5.2)",436        renderedMethod,437        "#endif",438      ])439    }), spacing: 2)440  }441  442  func specializeTypeName(_ typeName: String) -> String {443    // NOTE: Checking for an indicator prior to running `replacingOccurrences` is 4x faster.444    let concreteMockTypeName = mockableType.name + "Mock"445    446    if typeName.contains(SerializationRequest.Constants.selfTokenIndicator) {447      return typeName.replacingOccurrences(of: SerializationRequest.Constants.selfToken,448                                           with: concreteMockTypeName)449    }450    451    if typeName.contains(SerializationRequest.Constants.syntheticSelfTokenIndicator) {452      return typeName.replacingOccurrences(of: SerializationRequest.Constants.syntheticSelfToken,453                                           with: concreteMockTypeName)454    }455    456    return typeName...

Full Screen

Full Screen

MethodTemplate.swift

Source:MethodTemplate.swift Github

copy

Full Screen

...89    return String(lines: [90      "// MARK: Mocked \(fullNameForMocking)",91      FunctionDefinitionTemplate(attributes: method.attributes.safeDeclarations,92                                 declaration: declaration,93                                 genericConstraints: method.whereClauses.map({ context.specializeTypeName("\($0)") }),94                                 body: body).render(),95    ])96  }97  98  /// Declared in a class, or a class that the protocol conforms to.99  lazy var isClassBound: Bool = {100    let isClassDefinedProtocolConformance = context.protocolClassConformance != nil101      && method.isOverridable102    return context.mockableType.kind == .class || isClassDefinedProtocolConformance103  }()104  105  var overridableUniqueDeclaration: String {106    return "\(fullNameForMocking)\(returnTypeAttributesForMocking) -> \(mockableReturnType)\(genericConstraints)"107  }108  109  lazy var uniqueDeclaration: String = { return overridableUniqueDeclaration }()110  111  /// Methods synthesized specifically for the stubbing and verification APIs.112  var synthesizedDeclarations: String {113    let invocationType = "(\(separated: matchableParameterTypes)) \(returnTypeAttributesForMatching)-> \(matchableReturnType)"114    115    var methods = [String]()116    let genericTypes = [declarationTypeForMocking, invocationType, matchableReturnType]117    let returnType = "Mockingbird.Mockable<\(separated: genericTypes)>"118    119    let declaration = "public \(regularModifiers)func \(fullNameForMatching) -> \(returnType)"120    let genericConstraints = method.whereClauses.map({ context.specializeTypeName("\($0)") })121    122    let body = !context.shouldGenerateThunks ? MockableTypeTemplate.Constants.thunkStub : """123    return \(ObjectInitializationTemplate(124              name: "Mockingbird.Mockable",125              genericTypes: genericTypes,126              arguments: [("mock", mockObject), ("invocation", matchableInvocation())]))127    """128    methods.append(129      FunctionDefinitionTemplate(attributes: method.attributes.safeDeclarations,130                                 declaration: declaration,131                                 genericConstraints: genericConstraints,132                                 body: body).render())133    134    // Variadics generate both the array and variadic-forms of the function signature to allow use135    // of either when stubbing and verifying.136    if method.isVariadic {137      let body = !context.shouldGenerateThunks ? MockableTypeTemplate.Constants.thunkStub : """138      return \(ObjectInitializationTemplate(139                name: "Mockingbird.Mockable",140                genericTypes: genericTypes,141                arguments: [("mock", mockObject),142                            ("invocation", matchableInvocation(isVariadic: true))]))143      """144      let declaration = "public \(regularModifiers)func \(fullNameForMatchingVariadics) -> \(returnType)"145      methods.append(146        FunctionDefinitionTemplate(attributes: method.attributes.safeDeclarations,147                                   declaration: declaration,148                                   genericConstraints: genericConstraints,149                                   body: body).render())150    }151    152    return String(lines: methods, spacing: 2)153  }154  155  /// Modifiers specifically for stubbing and verification methods.156  lazy var regularModifiers: String = { return modifiers(allowOverride: false) }()157  /// Modifiers for mocked methods.158  lazy var overridableModifiers: String = { return modifiers(allowOverride: true) }()159  func modifiers(allowOverride: Bool = true) -> String {160    let isRequired = method.attributes.contains(.required)161    let required = (isRequired || method.isInitializer ? "required " : "")162    let shouldOverride = method.isOverridable && !isRequired && allowOverride163    let override = shouldOverride ? "override " : ""164    let `static` = method.kind.typeScope.isStatic ? "static " : ""165    return "\(required)\(override)\(`static`)"166  }167  168  lazy var genericTypes: [String] = {169    return method.genericTypes.map({ $0.flattenedDeclaration })170  }()171  172  lazy var genericConstraints: String = {173    guard !method.whereClauses.isEmpty else { return "" }174    return " where \(separated: method.whereClauses.map({ context.specializeTypeName("\($0)") }))"175  }()176  177  enum FunctionVariant {178    case function, subscriptGetter, subscriptSetter179    180    var isSubscript: Bool {181      switch self {182      case .function: return false183      case .subscriptGetter, .subscriptSetter: return true184      }185    }186  }187  188  enum FullNameMode {189    case mocking(variant: FunctionVariant)190    case matching(useVariadics: Bool, variant: FunctionVariant)191    case initializerProxy192    193    var isMatching: Bool {194      switch self {195      case .matching: return true196      case .mocking, .initializerProxy: return false197      }198    }199    200    var isInitializerProxy: Bool {201      switch self {202      case .matching, .mocking: return false203      case .initializerProxy: return true204      }205    }206    207    var useVariadics: Bool {208      switch self {209      case .matching(let useVariadics, _): return useVariadics210      case .mocking, .initializerProxy: return false211      }212    }213    214    var variant: FunctionVariant {215      switch self {216      case .matching(_, let variant), .mocking(let variant): return variant217      case .initializerProxy: return .function218      }219    }220  }221  222  func shortName(for mode: FullNameMode) -> String {223    let failable: String224    if mode.isInitializerProxy {225      failable = ""226    } else if method.attributes.contains(.failable) {227      failable = "?"228    } else if method.attributes.contains(.unwrappedFailable) {229      failable = "!"230    } else {231      failable = ""232    }233    234    // Don't escape initializers, subscripts, and special functions with reserved tokens like `==`.235    let shouldEscape = !method.isInitializer236      && method.kind != .functionSubscript237      && (method.shortName.first?.isLetter == true238        || method.shortName.first?.isNumber == true239        || method.shortName.first == "_")240    let escapedShortName = mode.isInitializerProxy ? "initialize" :241      (shouldEscape ? method.shortName.backtickWrapped : method.shortName)242    243    return genericTypes.isEmpty244      ? "\(escapedShortName)\(failable)"245      : "\(escapedShortName)\(failable)<\(separated: genericTypes)>"246  }247  248  lazy var fullNameForMocking: String = {249    return fullName(for: .mocking(variant: .function))250  }()251  lazy var fullNameForMatching: String = {252    return fullName(for: .matching(useVariadics: false, variant: .function))253  }()254  /// It's not possible to have an autoclosure with variadics. However, since a method can only have255  /// one variadic parameter, we can generate one method for wildcard matching using an argument256  /// matcher, and another for specific matching using variadics.257  lazy var fullNameForMatchingVariadics: String = {258    return fullName(for: .matching(useVariadics: true, variant: .function))259  }()260  func fullName(for mode: FullNameMode) -> String {261    let additionalParameters: [String]262    if mode.isInitializerProxy {263      additionalParameters = ["__file: StaticString = #file", "__line: UInt = #line"]264    } else if mode.variant == .subscriptSetter {265      let closureType = mode.isMatching ? "@autoclosure () -> " : ""266      additionalParameters = ["`newValue`: \(closureType)\(matchableReturnType)"]267    } else {268      additionalParameters = []269    }270    271    let parameterNames = method.parameters.map({ parameter -> String in272      let typeName: String273      if mode.isMatching && (!mode.useVariadics || !parameter.attributes.contains(.variadic)) {274        typeName = "@autoclosure () -> \(parameter.matchableTypeName(in: self))"275      } else {276        typeName = parameter.mockableTypeName(context: self)277      }278      let argumentLabel = parameter.argumentLabel ?? "_"279      let parameterName = parameter.name.backtickWrapped280      if argumentLabel.backtickUnwrapped != parameter.name {281        return "\(argumentLabel) \(parameterName): \(typeName)"282      } else if mode.isMatching && mode.variant.isSubscript {283        // Synthesized declarations for subscripts don't use argument labels (unless the parameter284        // name differs) for parity with bracket syntax.285        return "_ \(parameterName): \(typeName)"286      } else {287        return "\(parameterName): \(typeName)"288      }289    }) + additionalParameters290    291    let actualShortName = shortName(for: mode)292    let shortName: String293    if mode.isMatching, let resolvedShortName = Constants.reservedNamesMap[actualShortName] {294      shortName = resolvedShortName295    } else {296      shortName = actualShortName297    }298    299    return "\(shortName)(\(separated: parameterNames))"300  }301  302  lazy var mockableInvocation: String = {303    return ObjectInitializationTemplate(304      name: "Mockingbird.SwiftInvocation",305      arguments: [306        ("selectorName", "\(doubleQuoted: uniqueDeclaration)"),307        ("selectorType", "Mockingbird.SelectorType.method"),308        ("arguments", "[\(separated: mockArgumentMatchers)]"),309        ("returnType", "Swift.ObjectIdentifier(\(parenthetical: matchableReturnType).self)"),310      ]).render()311  }()312  313  func matchableInvocation(isVariadic: Bool = false) -> String {314    let matchers = isVariadic ? resolvedVariadicArgumentMatchers : resolvedArgumentMatchers315    return ObjectInitializationTemplate(316      name: "Mockingbird.SwiftInvocation",317      arguments: [318        ("selectorName", "\(doubleQuoted: uniqueDeclaration)"),319        ("selectorType", "Mockingbird.SelectorType.method"),320        ("arguments", "[\(matchers)]"),321        ("returnType", "Swift.ObjectIdentifier(\(parenthetical: matchableReturnType).self)"),322      ]).render()323  }324  325  lazy var resolvedArgumentMatchers: String = {326    return self.resolvedArgumentMatchers(for: method.parameters.map({ ($0.name, true) }))327  }()328  329  /// Variadic parameters cannot be resolved indirectly using `resolve()`.330  lazy var resolvedVariadicArgumentMatchers: String = {331    let parameters = method.parameters.map({ ($0.name, !$0.attributes.contains(.variadic)) })332    return resolvedArgumentMatchers(for: parameters)333  }()334  335  /// Can create argument matchers via resolving (shouldResolve = true) or by direct initialization.336  func resolvedArgumentMatchers(for parameters: [(name: String, shouldResolve: Bool)]) -> String {337    return String(list: parameters.map({ (name, shouldResolve) in338      let type = shouldResolve ? "resolve" : "ArgumentMatcher"339      return "Mockingbird.\(type)(\(name.backtickWrapped))"340    }))341  }342  343  lazy var returnTypeAttributesForMocking: String = {344    if method.attributes.contains(.rethrows) { return " rethrows" }345    if method.attributes.contains(.throws) { return " throws" }346    return ""347  }()348  349  lazy var returnTypeAttributesForMatching: String = {350    return method.isThrowing ? "throws " : ""351  }()352  353  lazy var declarationTypeForMocking: String = {354    if method.attributes.contains(.throws) {355      return "\(Declaration.throwingFunctionDeclaration)"356    } else {357      return "\(Declaration.functionDeclaration)"358    }359  }()360  361  lazy var mockArgumentMatchers: [String] = {362    return method.parameters.map({ parameter -> String in363      guard !parameter.isNonEscapingClosure else {364        // Can't save the argument in the invocation because it's a non-escaping closure type.365        return ObjectInitializationTemplate(366          name: "Mockingbird.ArgumentMatcher",367          arguments: [368            (nil, ObjectInitializationTemplate(369              name: "Mockingbird.NonEscapingClosure",370              genericTypes: [parameter.matchableTypeName(in: self)]).render())371          ]).render()372      }373      return ObjectInitializationTemplate(374        name: "Mockingbird.ArgumentMatcher",375        arguments: [(nil, "\(backticked: parameter.name)")]).render()376    })377  }()378  379  lazy var mockObject: String = {380    return method.kind.typeScope.isStatic ? "self.staticMock" : "self"381  }()382  383  /// Original function signature for casting to a matchable signature (variadics support).384  lazy var originalSignature: String = {385    let modifiers = method.isThrowing ? " throws" : ""386    let parameterTypes = method.parameters.map({387      $0.matchableTypeName(context: self, bridgeVariadics: false)388    })389    return "(\(separated: parameterTypes))\(modifiers) -> \(matchableReturnType)"390  }()391  392  /// General function signature for matching.393  lazy var longSignature: String = {394    let modifiers = method.isThrowing ? " throws" : ""395    return "(\(separated: matchableParameterTypes))\(modifiers) -> \(matchableReturnType)"396  }()397  398  /// Convenience function signature for matching without any arguments.399  lazy var shortSignature: String = {400    let modifiers = method.isThrowing ? " throws" : ""401    return "()\(modifiers) -> \(matchableReturnType)"402  }()403  404  lazy var mockableReturnType: String = {405    return context.specializeTypeName(method.returnTypeName)406  }()407  408  lazy var matchableReturnType: String = {409    return mockableReturnType.removingImplicitlyUnwrappedOptionals()410  }()411  412  lazy var mockableParameterTypes: [String] = {413    return method.parameters.map({ $0.mockableTypeName(context: self) })414  }()415  416  lazy var matchableParameterTypes: [String] = {417    return method.parameters.map({ $0.matchableTypeName(context: self) })418  }()419  420  lazy var invocationArguments: [(argumentLabel: String?, parameterName: String)] = {421    return method.parameters.map({ ($0.argumentLabel, $0.parameterName) })422  }()423}424extension Method {425  var isThrowing: Bool {426    return attributes.contains(.throws) || attributes.contains(.rethrows)427  }428  429  var isVariadic: Bool {430    return parameters.contains(where: { $0.attributes.contains(.variadic) })431  }432}433private extension MethodParameter {434  func mockableTypeName(context: MethodTemplate) -> String {435    return context.context.specializeTypeName(self.typeName)436  }437  438  func matchableTypeName(context: MethodTemplate, bridgeVariadics: Bool = true) -> String {439    let rawTypeName = mockableTypeName(context: context)440    441    // Type names outside of function declarations differ slightly. Variadics and implicitly442    // unwrapped optionals must be sanitized.443    let typeName = rawTypeName.removingImplicitlyUnwrappedOptionals()444    if bridgeVariadics && attributes.contains(.variadic) {445      return "[\(typeName.dropLast(3))]"446    } else {447      return "\(typeName)"448    }449  }450  451  var parameterName: String {452    let inoutAttribute = attributes.contains(.inout) ? "&" : ""453    let autoclosureForwarding = attributes.contains(.autoclosure) ? "()" : ""454    return "\(inoutAttribute)\(name.backtickWrapped)\(autoclosureForwarding)"455  }456  457  func matchableTypeName(in context: MethodTemplate) -> String {458    let typeName = context.context.specializeTypeName(self.typeName).removingParameterAttributes()459    if attributes.contains(.variadic) {460      return "[" + typeName + "]"461    } else {462      return typeName463    }464  }465  466  var isNonEscapingClosure: Bool {467    return attributes.contains(.closure) && !attributes.contains(.escaping)468  }469}...

Full Screen

Full Screen

specializeTypeName

Using AI Code Generation

copy

Full Screen

1import Foundation2func specializeTypeName<T>(_ type: T.Type) -> String {3    let name = String(describing: type)4    let components = name.components(separatedBy: ".")5}6class Person {7    init(name: String) {8    }9}10let person = Person(name: "John")11print(specializeTypeName(type(of: person)))12import Foundation13func specializeTypeName<T>(_ type: T.Type) -> String {14    let name = String(describing: type)15    let components = name.components(separatedBy: ".")16}17class Person {18    init(name: String) {19    }20}21let person = Person(name: "John")22print(specializeTypeName(type(of: person)))

Full Screen

Full Screen

specializeTypeName

Using AI Code Generation

copy

Full Screen

1print("a is \(a) and b is \(b)")2print("c is \(c)")3class A {4    func sum() -> Int {5    }6}7let a = A()8print("a is \(a.a) and b is \(a.b)")9let c = a.sum()10print("c is \(c)")11class A {12    func sum() -> Int {13    }14}15let a = A()16print("a is \(a.a) and b is \(a.b)")17let c = a.sum()18print("c is \(c)")19class A {20    func sum() -> Int {21    }22}23let a = A()24print("a is \(a.a) and b is \(a.b)")25let c = a.sum()26print("c is \(c)")27class A {28    func sum() -> Int {29    }30}31let a = A()32print("a is \(a.a) and b is \(a.b)")33let c = a.sum()34print("c is \(c)")35class A {36    func sum() -> Int {37    }38}39let a = A()40print("a is \(a.a) and b is \(a.b)")41let c = a.sum()42print("c is \(c)")43class A {44    func sum()

Full Screen

Full Screen

specializeTypeName

Using AI Code Generation

copy

Full Screen

1import Foundation2struct A {3}4struct B {5}6func specializeTypeName<T>(_ t: T.Type) -> String {7    return String(describing: t)8}9print(specializeTypeName(A.self))10print(specializeTypeName(B.self))11import Foundation12class A {13}14class B {15}16func specializeTypeName<T>(_ t: T.Type) -> String {17    return String(describing: t)18}19print(specializeTypeName(A.self))20print(specializeTypeName(B.self))21import Foundation22struct A {23}24struct B {25}26func specializeTypeName<T>(_ t: T.Type) -> String {27    return String(describing: t)28}29print(specializeTypeName(A.self))30print(specializeTypeName(B.self))31import Foundation32class A {33}34class B {35}36func specializeTypeName<T>(_ t: T.Type) -> String {37    return String(describing: t)38}39print(specializeTypeName(A.self))40print(specializeTypeName(B.self))41import Foundation42struct A {43}44struct B {45}46func specializeTypeName<T>(_ t: T.Type) -> String {47    return String(describing: t)48}49print(specializeTypeName(A.self))50print(specializeTypeName(B.self))51import Foundation

Full Screen

Full Screen

specializeTypeName

Using AI Code Generation

copy

Full Screen

1public func specializeTypeName<T>(_: T) -> String {2  return String(reflecting: T.self)3}4let s = specializeTypeName(1)5let s1 = specializeTypeName(1.0)6let s2 = specializeTypeName("Hello")7let s3 = specializeTypeName([1, 2, 3])8let s4 = specializeTypeName([1.0, 2.0, 3.0])9let s5 = specializeTypeName([1, 2, 3.0])10let s6 = specializeTypeName(["a", "b", "c"])11let s7 = specializeTypeName(["a", 1, "c"])12let s8 = specializeTypeName([1, 2, 3] as [Any])13let s9 = specializeTypeName([1, 2, 3] as [AnyObject])14let s10 = specializeTypeName([1, 2, 3] as [AnyHashable])15let s11 = specializeTypeName([1, 2, 3] as [AnyClass])16let s12 = specializeTypeName([1, 2, 3] as [AnyObject])17let s13 = specializeTypeName([1, 2, 3] as [AnyObject])18let s14 = specializeTypeName(["a": 1, "b": 2])

Full Screen

Full Screen

specializeTypeName

Using AI Code Generation

copy

Full Screen

1import Foundation2struct GenericStruct<T> {3}4func genericFunction<T>(value: T) {5    print("generic function")6}7func genericFunctionWithGenericParameter<T>(value: T, genericValue: GenericStruct<T>) {8    print("generic function with generic parameter")9}10func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {11    print("generic function with generic parameter and generic return type")12}13func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {14    print("generic function with generic parameter and generic return type")15}16func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {17    print("generic function with generic parameter and generic return type")18}19func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {20    print("generic function with generic parameter and generic return type")21}22func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {23    print("generic function with generic parameter and generic return type")24}25func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {26    print("generic function with generic parameter and generic return type")27}28func genericFunctionWithGenericParameterAndGenericReturnType<T>(value: T, genericValue: GenericStruct<T>) -> GenericStruct<T> {29    print("generic function with generic parameter and generic return type")30}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Mockingbird automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful