Skip to content

Commit 61f57df

Browse files
committed
šŸ› fix: incorrect inheritance/extensions when parent class is not scanned first (fix #47)
fix #47
1 parent 916897a commit 61f57df

File tree

6 files changed

+59
-21
lines changed

6 files changed

+59
-21
lines changed

ā€ŽSources/SwiftPlantUMLFramework/Internal/PlantUMLContext.swift

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import Foundation
33
class PlantUMLContext {
44
private(set) var configuration: Configuration
55

6+
// lookup the unique name (generated by SwiftPlantUML) for a given element
7+
var uniqueNameForElement: [SyntaxStructure: String] = [:]
8+
69
var uniqElementNames: [String] = []
710
var uniqElementAndTypes: [String: String] = [:]
811
// var style: [String: String] = [:]
@@ -102,6 +105,7 @@ class PlantUMLContext {
102105
uniqElementAndTypes[linkTypeKey] = linkTypeGeneric
103106
}
104107
}
108+
uniqueNameForElement[item] = newName
105109
return newName
106110
}
107111
}

ā€ŽSources/SwiftPlantUMLFramework/Internal/SyntaxStructure.swift

+2
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,5 @@ extension ElementKind: UnknownCaseRepresentable {
229229
/// `unknownCase` (abnormal situation)
230230
static let unknownCase: ElementKind = .other
231231
}
232+
233+
extension SyntaxStructure: Hashable {}

ā€ŽSources/SwiftPlantUMLFramework/PlantUMLScript.swift

+21-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public struct PlantUMLScript {
4545

4646
var replacingText = "\n"
4747

48-
for (index, element) in items.enumerated() {
48+
let orderedItems = items.orderedByExtensionsLast()
49+
for (index, element) in orderedItems.enumerated() {
4950
if let text = processStructureItem(item: element, index: index) {
5051
replacingText.appendAsNewLine(text)
5152
}
@@ -95,3 +96,22 @@ public struct PlantUMLScript {
9596
return item.plantuml(context: context) ?? nil
9697
}
9798
}
99+
100+
extension Array where Element == SyntaxStructure {
101+
/// order: non-extensions (i.e protocols, structs, classes, enums) first. Extensions last
102+
/// this ensures that linking is correct
103+
/// see https://github.com/MarcoEidinger/SwiftPlantUML/issues/47
104+
func orderedByExtensionsLast() -> [SyntaxStructure] {
105+
var ordered: [SyntaxStructure] = []
106+
var nonExtInsertPoint = 0
107+
forEach {
108+
if $0.kind == .extension {
109+
ordered.append($0)
110+
} else {
111+
ordered.insert($0, at: nonExtInsertPoint)
112+
nonExtInsertPoint += 1
113+
}
114+
}
115+
return ordered
116+
}
117+
}

ā€ŽTests/SwiftPlantUMLFrameworkTests/SyntaxStructureTests.swift

+12
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ final class SyntaxStructureTests: XCTestCase {
124124
XCTAssertTrue(plantUMLElement!.contains("~hasBasket : Bool"))
125125
}
126126

127+
func testOrderedByExtensionsLast() {
128+
let ext1 = SyntaxStructure(kind: .extension, name: "Ext1")
129+
let p1 = SyntaxStructure(kind: .protocol, name: "Protocol1")
130+
let c1 = SyntaxStructure(kind: .class, name: "Class1")
131+
let ext2 = SyntaxStructure(kind: .extension, name: "Ext2")
132+
let c2 = SyntaxStructure(kind: .class, name: "Class2")
133+
134+
let unordered = [ext1, p1, c1, ext2, c2]
135+
let ordered = unordered.orderedByExtensionsLast()
136+
XCTAssertEqual(ordered, [p1, c1, c2, ext1, ext2])
137+
}
138+
127139
func getTestFile() throws -> URL {
128140
// https://stackoverflow.com/questions/47177036/use-resources-in-unit-tests-with-swift-package-manager
129141
let path = Bundle.module.path(forResource: "demo", ofType: "txt", inDirectory: "TestData") ?? "nonesense"

ā€ŽTests/SwiftPlantUMLFrameworkTests/TestData/basics.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,6 @@ extension aPublicStruct: aProtocol {
8181
}
8282
}
8383

84-
struct anInternalStruct {
85-
var anInternalInstanceVar: Double
86-
private var aPrivateInstanceVar: Int
87-
private var aPublicInstanceVarTypeInference = "aString"
88-
}
89-
9084
extension anInternalStruct {
9185
var anExtensionComputedInstanceVar: String {
9286
"aString"
@@ -99,6 +93,12 @@ fileprivate extension anInternalStruct {
9993
}
10094
}
10195

96+
struct anInternalStruct {
97+
var anInternalInstanceVar: Double
98+
private var aPrivateInstanceVar: Int
99+
private var aPublicInstanceVarTypeInference = "aString"
100+
}
101+
102102
/// ignore comments :)
103103
public enum AnEnum {
104104

ā€ŽTests/SwiftPlantUMLFrameworkTests/TestData/basicsAsPlantUML.txt

+14-14
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ class "aPublicStruct" as aPublicStruct << (S, SkyBlue) struct >> {
4545
+aPublicInstanceMethod(param1:param2:)
4646
+{static} aStaticPublicInstanceMethod(param1:param2:)
4747
}
48+
class "anInternalStruct" as anInternalStruct << (S, SkyBlue) struct >> {
49+
~anInternalInstanceVar : Double
50+
-aPrivateInstanceVar : Int
51+
-aPublicInstanceVarTypeInference
52+
}
53+
class "AnEnum" as AnEnum << (E, LightSteelBlue) enum >> {
54+
+simpleCase
55+
+caseWithRaw(_:)
56+
+caseWithRaw(_:_:)
57+
~anInternalInstanceMethod()
58+
~{static} aStaticInternalMethod()
59+
~anInternalComputedVar : AnEnum
60+
}
4861
class "aPublicStruct" as aPublicStruct0 << (X, Orchid) extension >> {
4962
+anExtensionComputedInstanceVar : String
5063
+anExtensionInstanceMethod(param1:param2:)
@@ -53,27 +66,14 @@ class "aPublicStruct" as aPublicStruct1 << (X, Orchid) extension >> {
5366
~aProtocolInstanceVar : String
5467
~aProtocolInstanceMethod(param1:param2:)
5568
}
56-
class "anInternalStruct" as anInternalStruct << (S, SkyBlue) struct >> {
57-
~anInternalInstanceVar : Double
58-
-aPrivateInstanceVar : Int
59-
-aPublicInstanceVarTypeInference
60-
}
6169
class "anInternalStruct" as anInternalStruct2 << (X, Orchid) extension >> {
6270
~anExtensionComputedInstanceVar : String
6371
}
6472
class "anInternalStruct" as anInternalStruct3 << (X, Orchid) extension >> {
6573
-anFileprivateExtensionComputedInstanceVar : String
6674
}
67-
class "AnEnum" as AnEnum << (E, LightSteelBlue) enum >> {
68-
+simpleCase
69-
+caseWithRaw(_:)
70-
+caseWithRaw(_:_:)
71-
~anInternalInstanceMethod()
72-
~{static} aStaticInternalMethod()
73-
~anInternalComputedVar : AnEnum
74-
}
7575
aClass <|-- anInternalSubClass : inherits
76-
aPrivateGenericClass <|-- aPrivateGenericSubClass : inherits
76+
aPrivateGenericClass <|-- aPrivateGenericSubClass : inherits
7777
aProtocol <|.. aPublicStruct : confirms to
7878
aPublicStruct <.. aPublicStruct0 : ext
7979
aPublicStruct <.. aPublicStruct1 : ext

0 commit comments

Comments
Ā (0)