Skip to content

Commit

Permalink
Fixed nested type resolution in an extension with a global type name …
Browse files Browse the repository at this point in the history
…in the same module
  • Loading branch information
till0xff committed Nov 12, 2024
1 parent a6da5b0 commit b0e8317
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ internal struct ParserResultsComposed {
associatedTypes = Self.extractAssociatedTypes(parserResult)
parsedTypes = parserResult.types

var moduleAndTypeNameCollisions: Set<String> = []

for type in parsedTypes where !type.isExtension && type.parent == nil {
if let module = type.module, type.localName == module {
moduleAndTypeNameCollisions.insert(module)
}
}

// set definedInType for all methods and variables
parsedTypes
.forEach { type in
Expand All @@ -36,9 +44,17 @@ internal struct ParserResultsComposed {
}

// map all known types to their names

parsedTypes
.filter { !$0.isExtension }
.forEach {
let name = $0.name
// If a type name has the `<module>.` prefix, and the type `<module>.<module>` is undefined, we can safely remove the `<module>.` prefix
if let module = $0.module, name.hasPrefix(module), name.dropFirst(module.count).hasPrefix("."), !moduleAndTypeNameCollisions.contains(module) {
for type in $0.parentTypes where type.parent == nil {
type.localName.removeFirst(module.count + 1)
}
}
typeMap[$0.globalName] = $0
if let module = $0.module {
var typesByModules = modules[module, default: [:]]
Expand Down
1 change: 0 additions & 1 deletion SourceryRuntime/Sources/Generated/JSExport.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,6 @@ extension Type: TypeAutoJSExport {}
var set: SetType? { get }
var asSource: String { get }
var description: String { get }
var hash: Int { get }
var debugDescription: String { get }
}

Expand Down
37 changes: 35 additions & 2 deletions SourcerySwift/Sources/SourceryRuntime.content.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,14 @@ internal struct ParserResultsComposed {
associatedTypes = Self.extractAssociatedTypes(parserResult)
parsedTypes = parserResult.types
var moduleAndTypeNameCollisions: Set<String> = []
for type in parsedTypes where !type.isExtension && type.parent == nil {
if let module = type.module, type.localName == module {
moduleAndTypeNameCollisions.insert(module)
}
}
// set definedInType for all methods and variables
parsedTypes
.forEach { type in
Expand All @@ -2255,9 +2263,17 @@ internal struct ParserResultsComposed {
}
// map all known types to their names
parsedTypes
.filter { !$0.isExtension }
.forEach {
let name = $0.name
// If a type name has the `<module>.` prefix, and the type `<module>.<module>` is undefined, we can safely remove the `<module>.` prefix
if let module = $0.module, name.hasPrefix(module), name.dropFirst(module.count).hasPrefix("."), !moduleAndTypeNameCollisions.contains(module) {
for type in $0.parentTypes where type.parent == nil {
type.localName.removeFirst(module.count + 1)
}
}
typeMap[$0.globalName] = $0
if let module = $0.module {
var typesByModules = modules[module, default: [:]]
Expand All @@ -2274,7 +2290,12 @@ internal struct ParserResultsComposed {
/// Map associated types
associatedTypes.forEach {
typeMap[$0.key] = $0.value.type
if let globalName = $0.value.type?.globalName,
let type = typeMap[globalName] {
typeMap[$0.key] = type
} else {
typeMap[$0.key] = $0.value.type
}
}
types = unifyTypes()
Expand Down Expand Up @@ -3509,7 +3530,8 @@ public final class TemplateContext: NSObject, SourceryModel, NSCoding, Diffable
"based": types.based,
"inheriting": types.inheriting,
"implementing": types.implementing,
"protocolCompositions": types.protocolCompositions
"protocolCompositions": types.protocolCompositions,
"typealiases": types.typealiases
] as [String : Any],
"functions": functions,
"type": types.typesByName,
Expand Down Expand Up @@ -3547,6 +3569,9 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
/// module in which this typealias was declared
public var module: String?
/// Imports that existed in the file that contained this typealias declaration
public var imports: [Import] = []
/// typealias annotations
public var annotations: Annotations = [:]
Expand Down Expand Up @@ -3661,6 +3686,12 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
}; self.typeName = typeName
self.type = aDecoder.decode(forKey: "type")
self.module = aDecoder.decode(forKey: "module")
guard let imports: [Import] = aDecoder.decode(forKey: "imports") else {
withVaList(["imports"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.imports = imports
guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else {
withVaList(["annotations"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
Expand Down Expand Up @@ -3689,6 +3720,7 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
aCoder.encode(self.typeName, forKey: "typeName")
aCoder.encode(self.type, forKey: "type")
aCoder.encode(self.module, forKey: "module")
aCoder.encode(self.imports, forKey: "imports")
aCoder.encode(self.annotations, forKey: "annotations")
aCoder.encode(self.documentation, forKey: "documentation")
aCoder.encode(self.parent, forKey: "parent")
Expand Down Expand Up @@ -8506,6 +8538,7 @@ extension TypeName: TypeNameAutoJSExport {}
var typeName: TypeName { get }
var type: Type? { get }
var module: String? { get }
var imports: [Import] { get }
var annotations: Annotations { get }
var documentation: Documentation { get }
var parent: Type? { get }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ public enum Composer {
if baseType is Class {
type.inherits[baseType.name] = baseType
} else if let `protocol` = baseType as? SourceryProtocol {
type.implements[baseType.name] = baseType
type.implements[baseType.globalName] = baseType
if let extendingProtocol = type as? SourceryProtocol {
`protocol`.associatedTypes.forEach {
if extendingProtocol.associatedTypes[$0.key] == nil {
Expand Down Expand Up @@ -2246,6 +2246,14 @@ internal struct ParserResultsComposed {
associatedTypes = Self.extractAssociatedTypes(parserResult)
parsedTypes = parserResult.types
var moduleAndTypeNameCollisions: Set<String> = []
for type in parsedTypes where !type.isExtension && type.parent == nil {
if let module = type.module, type.localName == module {
moduleAndTypeNameCollisions.insert(module)
}
}
// set definedInType for all methods and variables
parsedTypes
.forEach { type in
Expand All @@ -2255,9 +2263,17 @@ internal struct ParserResultsComposed {
}
// map all known types to their names
parsedTypes
.filter { !$0.isExtension }
.forEach {
let name = $0.name
// If a type name has the `<module>.` prefix, and the type `<module>.<module>` is undefined, we can safely remove the `<module>.` prefix
if let module = $0.module, name.hasPrefix(module), name.dropFirst(module.count).hasPrefix("."), !moduleAndTypeNameCollisions.contains(module) {
for type in $0.parentTypes where type.parent == nil {
type.localName.removeFirst(module.count + 1)
}
}
typeMap[$0.globalName] = $0
if let module = $0.module {
var typesByModules = modules[module, default: [:]]
Expand All @@ -2274,7 +2290,12 @@ internal struct ParserResultsComposed {
/// Map associated types
associatedTypes.forEach {
typeMap[$0.key] = $0.value.type
if let globalName = $0.value.type?.globalName,
let type = typeMap[globalName] {
typeMap[$0.key] = type
} else {
typeMap[$0.key] = $0.value.type
}
}
types = unifyTypes()
Expand Down Expand Up @@ -3509,7 +3530,8 @@ public final class TemplateContext: NSObject, SourceryModel, NSCoding, Diffable
"based": types.based,
"inheriting": types.inheriting,
"implementing": types.implementing,
"protocolCompositions": types.protocolCompositions
"protocolCompositions": types.protocolCompositions,
"typealiases": types.typealiases
] as [String : Any],
"functions": functions,
"type": types.typesByName,
Expand Down Expand Up @@ -3547,6 +3569,9 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
/// module in which this typealias was declared
public var module: String?
/// Imports that existed in the file that contained this typealias declaration
public var imports: [Import] = []
/// typealias annotations
public var annotations: Annotations = [:]
Expand Down Expand Up @@ -3661,6 +3686,12 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
}; self.typeName = typeName
self.type = aDecoder.decode(forKey: "type")
self.module = aDecoder.decode(forKey: "module")
guard let imports: [Import] = aDecoder.decode(forKey: "imports") else {
withVaList(["imports"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
}
fatalError()
}; self.imports = imports
guard let annotations: Annotations = aDecoder.decode(forKey: "annotations") else {
withVaList(["annotations"]) { arguments in
NSException.raise(NSExceptionName.parseErrorException, format: "Key '%@' not found.", arguments: arguments)
Expand Down Expand Up @@ -3689,6 +3720,7 @@ public final class Typealias: NSObject, Typed, SourceryModel, Diffable {
aCoder.encode(self.typeName, forKey: "typeName")
aCoder.encode(self.type, forKey: "type")
aCoder.encode(self.module, forKey: "module")
aCoder.encode(self.imports, forKey: "imports")
aCoder.encode(self.annotations, forKey: "annotations")
aCoder.encode(self.documentation, forKey: "documentation")
aCoder.encode(self.parent, forKey: "parent")
Expand Down Expand Up @@ -9089,6 +9121,7 @@ extension TypeName: TypeNameAutoJSExport {}
var typeName: TypeName { get }
var type: Type? { get }
var module: String? { get }
var imports: [Import] { get }
var annotations: Annotations { get }
var documentation: Documentation { get }
var parent: Type? { get }
Expand Down
5 changes: 5 additions & 0 deletions SourceryTests/Parsing/ComposerSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2404,6 +2404,11 @@ class ParserComposerSpec: QuickSpec {
expect(types.map { $0.globalName }).to(equal(["Mod1.NS", "Mod2.NS.A", "Mod3.NS.B"]))
}

it("resolves extension of type with global parent name in same module") {
let types = parseModules(("A", "class Root {}; extension A.Root { struct Nested {} }")).types
expect(types.map(\.globalName).sorted()).to(equal(["A.Root", "A.Root.Nested"]))
}

it("resolves extensions of nested types properly") {
let code =
"""
Expand Down

0 comments on commit b0e8317

Please sign in to comment.