diff --git a/Configuration/Examples/Rich/.swiftplantuml.yml b/Configuration/Examples/Rich/.swiftplantuml.yml index e6bf00d..490946a 100644 --- a/Configuration/Examples/Rich/.swiftplantuml.yml +++ b/Configuration/Examples/Rich/.swiftplantuml.yml @@ -8,6 +8,7 @@ elements: - public showMembersWithAccessLevel: - public + - package - internal - private showGenerics: true @@ -74,4 +75,4 @@ texts: on several lines and using html legend: Some boxed text caption: Second to last - footer: The end \ No newline at end of file + footer: The end diff --git a/Configuration/Schema/json-schema-swiftplantuml.json b/Configuration/Schema/json-schema-swiftplantuml.json index 12c1f86..34cde90 100644 --- a/Configuration/Schema/json-schema-swiftplantuml.json +++ b/Configuration/Schema/json-schema-swiftplantuml.json @@ -18,12 +18,14 @@ "havingAccessLevel": [ "open", "public", + "package", "internal", "private" ], "showMembersWithAccessLevel": [ "open", "public", + "package", "internal", "private" ], diff --git a/Sources/SwiftPlantUMLFramework/Configuration/Configuration.swift b/Sources/SwiftPlantUMLFramework/Configuration/Configuration.swift index 168abf3..3075a45 100644 --- a/Sources/SwiftPlantUMLFramework/Configuration/Configuration.swift +++ b/Sources/SwiftPlantUMLFramework/Configuration/Configuration.swift @@ -6,6 +6,8 @@ public enum AccessLevel: String, Codable { case open /// `public` case `public` + /// `package` + case `package` /// `internal` case `internal` /// `private` diff --git a/Sources/SwiftPlantUMLFramework/Configuration/ElementOptions.swift b/Sources/SwiftPlantUMLFramework/Configuration/ElementOptions.swift index 90f0db6..67651d7 100644 --- a/Sources/SwiftPlantUMLFramework/Configuration/ElementOptions.swift +++ b/Sources/SwiftPlantUMLFramework/Configuration/ElementOptions.swift @@ -3,9 +3,9 @@ import Foundation /// Options which and how elements shall be considered for class diagram generation public struct ElementOptions: Codable { /// only elements (classes, structs, ...) with the specified access level will be processed and rendered in the class diagram - public private(set) var havingAccessLevel: [AccessLevel] = [.open, .public, .internal, .private] + public private(set) var havingAccessLevel: [AccessLevel] = [.open, .public, .package, .internal, .private] /// only members (properties and functions) with the specified access level will be processed and renderd in the class diagram - public private(set) var showMembersWithAccessLevel: [AccessLevel] = [.open, .public, .internal, .private] + public private(set) var showMembersWithAccessLevel: [AccessLevel] = [.open, .public, .package, .internal, .private] /// show nested types public private(set) var showNestedTypes: Bool = true @@ -57,8 +57,8 @@ public struct ElementOptions: Codable { /// memberwise initializer public init( - havingAccessLevel: [AccessLevel] = [.open, .public, .internal, .private], - showMembersWithAccessLevel: [AccessLevel] = [.open, .public, .internal, .private], + havingAccessLevel: [AccessLevel] = [.open, .public, .package, .internal, .private], + showMembersWithAccessLevel: [AccessLevel] = [.open, .public, .package, .internal, .private], showNestedTypes: Bool = true, showGenerics: Bool = true, showExtensions: ExtensionVisualization? = nil, diff --git a/Sources/SwiftPlantUMLFramework/Internal/ElementAccessibility+Extensions.swift b/Sources/SwiftPlantUMLFramework/Internal/ElementAccessibility+Extensions.swift index 9da9983..b8e03b3 100644 --- a/Sources/SwiftPlantUMLFramework/Internal/ElementAccessibility+Extensions.swift +++ b/Sources/SwiftPlantUMLFramework/Internal/ElementAccessibility+Extensions.swift @@ -5,7 +5,7 @@ extension ElementAccessibility { switch self { case .public, .open: return "+" - case .internal: + case .internal, .package: return "~" case .private, .fileprivate: return "-" diff --git a/Sources/SwiftPlantUMLFramework/Internal/SyntaxStructure.swift b/Sources/SwiftPlantUMLFramework/Internal/SyntaxStructure.swift index 146f625..643d0a0 100644 --- a/Sources/SwiftPlantUMLFramework/Internal/SyntaxStructure.swift +++ b/Sources/SwiftPlantUMLFramework/Internal/SyntaxStructure.swift @@ -87,6 +87,8 @@ internal enum ElementAccessibility: String, RawRepresentable, Comparable { case open = "source.lang.swift.accessibility.open" /// `public` case `public` = "source.lang.swift.accessibility.public" + /// `package` + case package = "source.lang.swift.accessibility.package" /// `internal` case `internal` = "source.lang.swift.accessibility.internal" /// `private` @@ -99,8 +101,10 @@ internal enum ElementAccessibility: String, RawRepresentable, Comparable { private var value: Int { switch self { case .open: - return 6 + return 7 case .public: + return 6 + case .package: return 5 case .internal: return 4 @@ -119,6 +123,8 @@ internal enum ElementAccessibility: String, RawRepresentable, Comparable { self.init(rawValue: "source.lang.swift.accessibility.open") case .public: self.init(rawValue: "source.lang.swift.accessibility.public") + case .package: + self.init(rawValue: "source.lang.swift.accessibility.package") case .internal: self.init(rawValue: "source.lang.swift.accessibility.internal") case .private: diff --git a/Tests/SwiftPlantUMLFrameworkTests/ConfigurationTests.swift b/Tests/SwiftPlantUMLFrameworkTests/ConfigurationTests.swift index 95b6fd0..800437a 100644 --- a/Tests/SwiftPlantUMLFrameworkTests/ConfigurationTests.swift +++ b/Tests/SwiftPlantUMLFrameworkTests/ConfigurationTests.swift @@ -4,8 +4,8 @@ import XCTest final class PlantUMLConfigurationTests: XCTestCase { func testDefault() { let config = Configuration() - XCTAssertEqual(config.elements.havingAccessLevel.count, 4) - XCTAssertEqual(config.elements.showMembersWithAccessLevel.count, 4) + XCTAssertEqual(config.elements.havingAccessLevel.count, 5) + XCTAssertEqual(config.elements.showMembersWithAccessLevel.count, 5) } func testDecodingObsoleteShowExtensionsBooleanProperty() { diff --git a/Tests/SwiftPlantUMLFrameworkTests/ElementAccessibilityTests.swift b/Tests/SwiftPlantUMLFrameworkTests/ElementAccessibilityTests.swift index 23b7289..369db12 100644 --- a/Tests/SwiftPlantUMLFrameworkTests/ElementAccessibilityTests.swift +++ b/Tests/SwiftPlantUMLFrameworkTests/ElementAccessibilityTests.swift @@ -4,8 +4,10 @@ import XCTest final class ElementAccessibilityTests: XCTestCase { func testComparison() { XCTAssertTrue(ElementAccessibility.open > ElementAccessibility.public) + XCTAssertTrue(ElementAccessibility.public > ElementAccessibility.package) XCTAssertTrue(ElementAccessibility.public > ElementAccessibility.internal) XCTAssertTrue(ElementAccessibility.public > ElementAccessibility.private) + XCTAssertTrue(ElementAccessibility.package > ElementAccessibility.internal) XCTAssertTrue(ElementAccessibility.internal > ElementAccessibility.private) XCTAssertTrue(ElementAccessibility.private > ElementAccessibility.fileprivate) XCTAssertTrue(ElementAccessibility.private > ElementAccessibility.other) @@ -15,6 +17,7 @@ final class ElementAccessibilityTests: XCTestCase { func testIndicator() { XCTAssertEqual(ElementAccessibility.open.indicator, "+") XCTAssertEqual(ElementAccessibility.public.indicator, "+") + XCTAssertEqual(ElementAccessibility.package.indicator, "~") XCTAssertEqual(ElementAccessibility.internal.indicator, "~") XCTAssertEqual(ElementAccessibility(orig: .internal)?.indicator, "~") XCTAssertEqual(ElementAccessibility.private.indicator, "-") diff --git a/Tests/SwiftPlantUMLFrameworkTests/PlantUMLScriptTests.swift b/Tests/SwiftPlantUMLFrameworkTests/PlantUMLScriptTests.swift index 27f721c..c4590fc 100644 --- a/Tests/SwiftPlantUMLFrameworkTests/PlantUMLScriptTests.swift +++ b/Tests/SwiftPlantUMLFrameworkTests/PlantUMLScriptTests.swift @@ -107,6 +107,17 @@ final class PlantUMLScriptTests: XCTestCase { XCTAssertTrue(script.text.contains(headerText)) } + func testPackageAccessModifierE2E() { + guard let items = try! SyntaxStructure.create(from: getTestFile(named: "packageAccessModifier"))?.substructure else { return XCTFail("cannot read test data") } + let script = PlantUMLScript(items: items) + let expected = try! getTestFileContent(named: "packageAccessModifierAsPlantUML") + #if swift(>=5.9) + XCTAssertEqual(script.text.noSpacesAndNoLineBreaks, expected.noSpacesAndNoLineBreaks) + #else + XCTAssertNotNil("Compiling SwiftPlantUML with a lower Swift version will have incorrect result, i.e. ~{static}package()~aStaticPackageInstanceMethod()") + #endif + } + func getTestFile(named: String = "basics") throws -> URL { // https://stackoverflow.com/questions/47177036/use-resources-in-unit-tests-with-swift-package-manager let path = Bundle.module.path(forResource: named, ofType: "txt", inDirectory: "TestData") ?? "nonesense" diff --git a/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifier.txt b/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifier.txt new file mode 100644 index 0000000..31eb1ad --- /dev/null +++ b/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifier.txt @@ -0,0 +1,5 @@ +import Foundation + +package struct anPackageInternalStruct { + static package func aStaticPackageInstanceMethod() +} \ No newline at end of file diff --git a/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifierAsPlantUML.txt b/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifierAsPlantUML.txt new file mode 100644 index 0000000..b7e41b3 --- /dev/null +++ b/Tests/SwiftPlantUMLFrameworkTests/TestData/packageAccessModifierAsPlantUML.txt @@ -0,0 +1,11 @@ +@startuml +' STYLE START +hide empty members +skinparam shadowing false +' STYLE END +set namespaceSeparator none + + +class "anPackageInternalStruct" as anPackageInternalStruct << (S, SkyBlue) struct >> { ~{static} aStaticPackageInstanceMethod() +} +@enduml