diff --git a/SourceryRuntime/Sources/Common/Composer/ParserResultsComposed.swift b/SourceryRuntime/Sources/Common/Composer/ParserResultsComposed.swift index ef6cde026..0041c532f 100644 --- a/SourceryRuntime/Sources/Common/Composer/ParserResultsComposed.swift +++ b/SourceryRuntime/Sources/Common/Composer/ParserResultsComposed.swift @@ -27,6 +27,14 @@ internal struct ParserResultsComposed { associatedTypes = Self.extractAssociatedTypes(parserResult) parsedTypes = parserResult.types + var moduleAndTypeNameCollisions: Set = [] + + 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 @@ -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 `.` prefix, and the type `.` is undefined, we can safely remove the `.` 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: [:]] diff --git a/SourceryRuntime/Sources/Generated/JSExport.generated.swift b/SourceryRuntime/Sources/Generated/JSExport.generated.swift index dbdba7776..a9209f03a 100644 --- a/SourceryRuntime/Sources/Generated/JSExport.generated.swift +++ b/SourceryRuntime/Sources/Generated/JSExport.generated.swift @@ -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 } } diff --git a/SourcerySwift/Sources/SourceryRuntime.content.generated.swift b/SourcerySwift/Sources/SourceryRuntime.content.generated.swift index 28f02a73a..8e0abf10d 100644 --- a/SourcerySwift/Sources/SourceryRuntime.content.generated.swift +++ b/SourcerySwift/Sources/SourceryRuntime.content.generated.swift @@ -2246,6 +2246,14 @@ internal struct ParserResultsComposed { associatedTypes = Self.extractAssociatedTypes(parserResult) parsedTypes = parserResult.types + var moduleAndTypeNameCollisions: Set = [] + + 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 @@ -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 `.` prefix, and the type `.` is undefined, we can safely remove the `.` 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: [:]] @@ -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() @@ -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, @@ -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 = [:] @@ -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) @@ -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") @@ -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 } diff --git a/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift b/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift index 90e789b06..9b2de4000 100644 --- a/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift +++ b/SourcerySwift/Sources/SourceryRuntime_Linux.content.generated.swift @@ -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 { @@ -2246,6 +2246,14 @@ internal struct ParserResultsComposed { associatedTypes = Self.extractAssociatedTypes(parserResult) parsedTypes = parserResult.types + var moduleAndTypeNameCollisions: Set = [] + + 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 @@ -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 `.` prefix, and the type `.` is undefined, we can safely remove the `.` 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: [:]] @@ -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() @@ -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, @@ -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 = [:] @@ -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) @@ -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") @@ -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 } diff --git a/SourceryTests/Parsing/ComposerSpec.swift b/SourceryTests/Parsing/ComposerSpec.swift index 2bae5b5bb..9d5f7b4d7 100644 --- a/SourceryTests/Parsing/ComposerSpec.swift +++ b/SourceryTests/Parsing/ComposerSpec.swift @@ -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 = """