How to use actualTypeNames method of TypealiasRepository class

Best Mockingbird code snippet using TypealiasRepository.actualTypeNames

Run Mockingbird automation tests on LambdaTest cloud grid

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

SerializationRequest.swift

Source: SerializationRequest.swift Github

copy
1//
2//  SerializationRequest.swift
3//  MockingbirdGenerator
4//
5//  Created by Andrew Chang on 9/7/19.
6//
7
8import Foundation
9
10/// Fully qualifies tokenized `DeclaredType` objects given a declaration context.
11struct SerializationRequest {
12  enum Constants {
13    static let selfTokenIndicator = "#"
14    /// `Self` substitution using the final mock type.
15    static let selfToken = "#Self#"
16    
17    static let syntheticSelfTokenIndicator = "%"
18    /// Same as `selfToken`, but created by the generator and doesn't affect generics.
19    static let syntheticSelfToken = "%Self%"
20  }
21  
22  enum Method: String {
23    /// No qualification.
24    case notQualified = "notQualified"
25    /// Qualified from the referencing scope.
26    case contextQualified = "contextQualified"
27    /// Fully qualified from the module scope.
28    case moduleQualified = "moduleQualified"
29    /// Fully qualified, resolved aliased type names.
30    case actualTypeName = "actualTypeName"
31  }
32  
33  struct Options: OptionSet, Hashable {
34    let rawValue: Int
35    init(rawValue: Int) {
36      self.rawValue = rawValue
37    }
38    
39    static let shouldTokenizeSelf = Options(rawValue: 1 << 0)
40    static let shouldExcludeArgumentLabels = Options(rawValue: 1 << 1)
41    static let shouldExcludeImplicitlyUnwrappedOptionals = Options(rawValue: 1 << 2)
42    static let shouldSpecializeTypes = Options(rawValue: 1 << 3)
43    
44    static let standard: Options = [.shouldTokenizeSelf, .shouldExcludeArgumentLabels]
45  }
46  
47  class Context {
48    let moduleNames: [String]
49    let referencingModuleName: String? // The module referencing the type in some declaration.
50    let containingTypeNames: ArraySlice<String>
51    let containingScopes: ArraySlice<String>
52    let rawTypeRepository: RawTypeRepository?
53    let typealiasRepository: TypealiasRepository?
54    let genericTypeContext: [[String]]
55    let excludedGenericTypeNames: Set<String>
56    let specializationContext: SpecializationContext?
57    
58    init(moduleNames: [String],
59         referencingModuleName: String?,
60         containingTypeNames: ArraySlice<String>,
61         containingScopes: ArraySlice<String>,
62         rawTypeRepository: RawTypeRepository?,
63         typealiasRepository: TypealiasRepository? = nil,
64         genericTypeContext: [[String]],
65         excludedGenericTypeNames: Set<String> = [],
66         specializationContext: SpecializationContext? = nil) {
67      self.moduleNames = moduleNames
68      self.referencingModuleName = referencingModuleName
69      self.containingTypeNames = containingTypeNames
70      self.containingScopes = containingScopes
71      self.rawTypeRepository = rawTypeRepository
72      self.typealiasRepository = typealiasRepository
73      self.genericTypeContext = genericTypeContext
74      self.excludedGenericTypeNames = excludedGenericTypeNames
75      self.specializationContext = specializationContext
76    }
77    
78    convenience init(moduleNames: [String],
79                     rawType: RawType,
80                     rawTypeRepository: RawTypeRepository,
81                     typealiasRepository: TypealiasRepository? = nil) {
82      self.init(moduleNames: moduleNames,
83                referencingModuleName: rawType.parsedFile.moduleName,
84                containingTypeNames: rawType.containingTypeNames[...] + [rawType.name],
85                containingScopes: rawType.containingScopes[...] + [rawType.name],
86                rawTypeRepository: rawTypeRepository,
87                typealiasRepository: typealiasRepository,
88                genericTypeContext: rawType.genericTypeContext + [rawType.genericTypes])
89    }
90    
91    convenience init(from context: Context,
92                     moduleNames: [String]? = nil,
93                     referencingModuleName: String? = nil,
94                     containingTypeNames: ArraySlice<String>? = nil,
95                     containingScopes: ArraySlice<String>? = nil,
96                     rawTypeRepository: RawTypeRepository? = nil,
97                     typealiasRepository: TypealiasRepository? = nil,
98                     genericTypeContext: [[String]]? = nil,
99                     excludedGenericTypeNames: Set<String>? = nil,
100                     specializationContext: SpecializationContext? = nil) {
101      self.init(moduleNames: moduleNames ?? context.moduleNames,
102                referencingModuleName: referencingModuleName ?? context.referencingModuleName,
103                containingTypeNames: containingTypeNames ?? context.containingTypeNames,
104                containingScopes: containingScopes ?? context.containingScopes,
105                rawTypeRepository: rawTypeRepository ?? context.rawTypeRepository,
106                typealiasRepository: typealiasRepository ?? context.typealiasRepository,
107                genericTypeContext: genericTypeContext ?? context.genericTypeContext,
108                excludedGenericTypeNames: excludedGenericTypeNames ?? context.excludedGenericTypeNames,
109                specializationContext: specializationContext ?? context.specializationContext)
110    }
111    
112    convenience init() {
113      self.init(moduleNames: [],
114                referencingModuleName: nil,
115                containingTypeNames: [],
116                containingScopes: [],
117                rawTypeRepository: nil,
118                typealiasRepository: nil,
119                genericTypeContext: [],
120                excludedGenericTypeNames: [],
121                specializationContext: nil)
122    }
123    
124    /// typeName => method => serialized
125    fileprivate var memoizedTypeNames = [String: [String: String]]()
126  }
127  
128  let method: Method
129  let context: Context
130  let options: Options
131}
132
133protocol SerializableType {
134  func serialize(with request: SerializationRequest) -> String
135}
136
137extension SerializationRequest {
138  /// Given a `typeName`, serialize it based on the current request context and method.
139  /// - Parameter typeName: A type name which should be stripped of whitespace.
140  func serialize(_ typeName: String) -> String {
141    guard typeName != "Self" else { // `Self` can never be typealiased away.
142      return (options.contains(.shouldTokenizeSelf) ? Constants.selfToken : typeName)
143    }
144    
145    guard !typeName.hasPrefix("Self.") else {
146      return options.contains(.shouldTokenizeSelf)
147        ? Constants.selfToken + typeName[typeName.index(typeName.startIndex, offsetBy: 4)...]
148        : typeName
149    }
150    
151    guard method != .notQualified,
152      let rawTypeRepository = context.rawTypeRepository,
153      let referencingModuleName = context.referencingModuleName else {
154        return typeName // This is a non-qualifying serialization request.
155    }
156    
157    if let memoized = context.memoizedTypeNames[typeName]?[method.rawValue] {
158      return memoized
159    }
160    
161    // Recursively specialize generic types that exist in the current specialization context.
162    if options.contains(.shouldSpecializeTypes), let specialized = specialize(typeName) {
163      return specialized
164    }
165    
166    // Don't qualify generic types which could be shadowing types defined at the module level.
167    guard !context.genericTypeContext.contains(where: { $0.contains(typeName) }) else {
168      return serializeGenericTypes(typeName)
169    }
170    
171    // Resolve the type name to a raw type instance.
172    guard let baseRawType = rawTypeRepository
173      .nearestInheritedType(named: typeName,
174                            trimmedName: typeName.removingGenericTyping(),
175                            moduleNames: context.moduleNames,
176                            referencingModuleName: context.referencingModuleName,
177                            containingTypeNames: context.containingTypeNames)?
178      .findBaseRawType() else { return serializeGenericTypes(typeName) }
179    
180    // Get the actual module name of the definition since the base raw type could be a (nested)
181    // enum or class defined within an extension.
182    var definingModuleName: String? {
183      if baseRawType.definedInExtension {
184        guard let extensionTypeName = baseRawType.containingTypeNames.first else { return nil }
185        guard let extensionRawType = rawTypeRepository
186          .nearestInheritedType(named: extensionTypeName,
187                                trimmedName: extensionTypeName.removingGenericTyping(),
188                                moduleNames: context.moduleNames,
189                                referencingModuleName: context.referencingModuleName,
190                                containingTypeNames: [])?
191          .findBaseRawType() else {
192            logWarning(
193              "Cannot resolve module name for containing type \(extensionTypeName.singleQuoted) which is not defined in the project or in a supporting source file",
194              diagnostic: .undefinedType,
195              filePath: baseRawType.parsedFile.path,
196              line: SourceSubstring.key
197                .extractLinesNumbers(from: baseRawType.dictionary,
198                                     contents: baseRawType.parsedFile.file.contents)?.start
199            )
200            return nil
201        }
202        return extensionRawType.parsedFile.moduleName
203      } else {
204        return baseRawType.parsedFile.moduleName
205      }
206    }
207    
208    let qualifiedTypeNames = baseRawType
209      .qualifiedModuleNames(from: typeName,
210                            context: context.containingScopes,
211                            definingModuleName: definingModuleName)
212    context.memoizedTypeNames[typeName]?[Method.contextQualified.rawValue] =
213      qualifiedTypeNames.contextQualified
214    context.memoizedTypeNames[typeName]?[Method.moduleQualified.rawValue] =
215      qualifiedTypeNames.moduleQualified
216    
217    switch method {
218    case .contextQualified:
219      return serializeGenericTypes(qualifiedTypeNames.contextQualified)
220      
221    case .moduleQualified:
222      // Nested type aliases referenced from an inherited context should use Self qualification.
223      // TODO: Workaround shadowed type aliases: https://bugs.swift.org/browse/TF-1279
224      if baseRawType.kind == .typealias && baseRawType.isContainedType &&
225        qualifiedTypeNames.contextQualified.count < qualifiedTypeNames.moduleQualified.count {
226        return Constants.syntheticSelfToken + "." +
227          serializeGenericTypes(qualifiedTypeNames.contextQualified)
228      }
229      
230      // Exclude the module name if it's shadowed by a type in one of the imported modules. This
231      // will break if the shadowed module also contains type names that conflict with another
232      // module. However, name conflicts are much less likely to occur than module name shadowing.
233      if rawTypeRepository.isModuleNameShadowed(moduleName: baseRawType.parsedFile.moduleName) {
234        let partiallyQualifiedTypeName = qualifiedTypeNames.moduleQualified
235          .substringComponents(separatedBy: ".")[1...]
236          .joined(separator: ".")
237        return serializeGenericTypes(partiallyQualifiedTypeName)
238      } else {
239        return serializeGenericTypes(qualifiedTypeNames.moduleQualified)
240      }
241      
242    case .actualTypeName:
243      guard let typealiasRepository = context.typealiasRepository else { return typeName }
244      let actualTypeNames = typealiasRepository
245        .actualTypeNames(for: qualifiedTypeNames.moduleQualified,
246                         rawTypeRepository: rawTypeRepository,
247                         moduleNames: context.moduleNames,
248                         referencingModuleName: referencingModuleName,
249                         containingTypeNames: context.containingTypeNames)
250      let flattenedTypeNames = actualTypeNames.joined(separator: " & ")
251      context.memoizedTypeNames[typeName]?[Method.actualTypeName.rawValue] = flattenedTypeNames
252      return serializeGenericTypes(flattenedTypeNames)
253      
254    case .notQualified: return typeName
255    }
256  }
257  
258  private func specialize(_ typeName: String) -> String? {
259    guard
260      let specialization = context.specializationContext?.specializations[typeName],
261      !context.excludedGenericTypeNames.contains(typeName)
262      else {
263        return nil
264    }
265    
266    // Handle shadowed generic type parameter names by excluding types once specialized, e.g.
267    // class One<T>
268    // class Two<T>: One<T> { One.T => T }
269    // class Three: Two<String> { Two.T => String }
270    let attributedContext = SerializationRequest.Context(
271      from: context,
272      excludedGenericTypeNames: context.excludedGenericTypeNames.union([typeName])
273    )
274    let attributedRequest = SerializationRequest(method: method,
275                                                 context: attributedContext,
276                                                 options: options)
277    let serialized = specialization.serialize(with: attributedRequest)
278    return serializeGenericTypes(serialized, attributedRequest: attributedRequest)
279  }
280  
281  private func serializeGenericTypes(_ typeName: String,
282                                     attributedRequest: SerializationRequest? = nil) -> String {
283    guard typeName.contains("<") else { return typeName } // Fast path.
284    let request = attributedRequest ?? self
285    
286    let declaredType = DeclaredType(from: typeName)
287    switch declaredType {
288    case .tuple: break
289    case .single(let single, _):
290      switch single {
291      case .list, .map, .function: break
292      case .nominal(let components):
293        return components
294          .map({ component -> String in
295            guard !component.genericTypes.isEmpty else { return component.typeName } // Fast path.
296            let serializedGenericTypes = component.genericTypes
297              .map({ $0.serialize(with: request) })
298            return "\(component.typeName)<\(serializedGenericTypes.joined(separator: ", "))>"
299          })
300          .joined(separator: ".")
301      }
302    }
303    
304    return typeName
305  }
306}
307
Full Screen

Typealias.swift

Source: Typealias.swift Github

copy
1//
2//  Typealias.swift
3//  MockingbirdCli
4//
5//  Created by Andrew Chang on 8/29/19.
6//
7
8import Foundation
9import SourceKittenFramework
10
11struct Typealias {
12  let name: String
13  let typeNames: [String] // Possible that this references another typealias or multiple types.
14  let rawType: RawType
15  
16  init?(from rawType: RawType) {
17    guard let kind = SwiftDeclarationKind(from: rawType.dictionary), kind == .typealias,
18      let name = rawType.dictionary[SwiftDocKey.name.rawValue] as? String
19      else { return nil }
20    self.name = name
21    self.rawType = rawType
22    
23    guard let typeNames = Typealias.parseTypeNames(from: rawType.dictionary,
24                                                   parsedFile: rawType.parsedFile)
25      else { return nil }
26    self.typeNames = typeNames
27  }
28  
29  static func parseTypeNames(from dictionary: StructureDictionary,
30                             parsedFile: ParsedFile) -> [String]? {
31    let source = parsedFile.data
32    guard let rawDeclaration = SourceSubstring.nameSuffix.extract(from: dictionary,
33                                                                  contents: source),
34      let declarationIndex = rawDeclaration.firstIndex(of: "=") else { return nil }
35    let declaration = rawDeclaration[rawDeclaration.index(after: declarationIndex)...]
36    return declaration.substringComponents(separatedBy: "&").map({
37      $0.trimmingCharacters(in: .whitespacesAndNewlines)
38    })
39  }
40}
41
42class TypealiasRepository {
43  /// Fully qualified (module) typealias name => `Typealias`
44  private(set) var typealiases = [String: Typealias]()
45  /// Fully qualified (module) typealias name => actual fully qualified (module) type name
46  private var unwrappedTypealiases = Synchronized<[String: [String]]>([:])
47  
48  /// Start tracking a typealias.
49  func addTypealias(_ typeAlias: Typealias) {
50    typealiases[typeAlias.rawType.fullyQualifiedModuleName] = typeAlias
51  }
52  
53  /// Returns the actual fully qualified type name for a given fully qualified (module) type name.
54  func actualTypeNames(for typeName: String,
55                       rawTypeRepository: RawTypeRepository,
56                       moduleNames: [String],
57                       referencingModuleName: String,
58                       containingTypeNames: ArraySlice<String>) -> [String] {
59    guard let typeAlias = typealiases[typeName] else { return [typeName] }
60    return actualTypeNames(for: typeAlias,
61                           rawTypeRepository: rawTypeRepository,
62                           moduleNames: moduleNames,
63                           referencingModuleName: referencingModuleName,
64                           containingTypeNames: containingTypeNames)
65  }
66  
67  /// Returns the actual type name for a given `Typealias`, if one exists.
68  func actualTypeNames(for typeAlias: Typealias,
69                       rawTypeRepository: RawTypeRepository,
70                       moduleNames: [String],
71                       referencingModuleName: String,
72                       containingTypeNames: ArraySlice<String>) -> [String] {
73    // This typealias is already resolved.
74    if let actualTypeNames = unwrappedTypealiases.read({
75      $0[typeAlias.rawType.fullyQualifiedModuleName]
76    }) {
77      return actualTypeNames
78    }
79    
80    // Get the fully qualified name of the referenced type.
81    let aliasedRawTypeNames = typeAlias.typeNames.map({ typeName -> String in
82      guard let qualifiedTypeName = rawTypeRepository
83        .nearestInheritedType(named: typeName,
84                              moduleNames: moduleNames,
85                              referencingModuleName: referencingModuleName,
86                              containingTypeNames: containingTypeNames)?
87        .findBaseRawType()?.fullyQualifiedModuleName
88        else { return typeName }
89      return qualifiedTypeName
90    })
91    
92    // Check if the typealias references another typealias.
93    let unwrappedNames = aliasedRawTypeNames.flatMap({ aliasedRawTypeName -> [String] in
94      guard let aliasedTypealias = typealiases[aliasedRawTypeName] else {
95        return [aliasedRawTypeName]
96      }
97      return actualTypeNames(for: aliasedTypealias,
98                             rawTypeRepository: rawTypeRepository,
99                             moduleNames: moduleNames,
100                             referencingModuleName: aliasedTypealias.rawType.parsedFile.moduleName,
101                             containingTypeNames: aliasedTypealias.rawType.containingTypeNames[...])
102    })
103    unwrappedTypealiases.update {
104      $0[typeAlias.rawType.fullyQualifiedModuleName] = unwrappedNames
105    }
106    return unwrappedNames
107  }
108}
109
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Most used method in TypealiasRepository

Trigger actualTypeNames code on LambdaTest Cloud Grid

Execute automation tests with actualTypeNames on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)