diff --git a/Sources/FoundationEssentials/AttributedString/AttributeScope.swift b/Sources/FoundationEssentials/AttributedString/AttributeScope.swift index c7160cf97..656bf27cb 100644 --- a/Sources/FoundationEssentials/AttributedString/AttributeScope.swift +++ b/Sources/FoundationEssentials/AttributedString/AttributeScope.swift @@ -172,7 +172,7 @@ internal func _loadDefaultAttributes() -> [String : any AttributedStringKey.Type // TODO: Support AttributeScope key finding in FoundationPreview @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) -internal extension AttributeScope { +extension AttributeScope { private static var scopeDescription: ScopeDescription { if let cached = _loadedScopeCache.withLock({ $0[Self.self] }) { return cached @@ -198,13 +198,17 @@ internal extension AttributeScope { return desc } - static func attributeKeyTypes() -> [String : any AttributedStringKey.Type] { + internal static func attributeKeyTypes() -> [String : any AttributedStringKey.Type] { Self.scopeDescription.attributes } - static func markdownKeyTypes() -> [String : any MarkdownDecodableAttributedStringKey.Type] { + internal static func markdownKeyTypes() -> [String : any MarkdownDecodableAttributedStringKey.Type] { Self.scopeDescription.markdownAttributes } + + @available(FoundationPreview 6.2, *) + public static var attributeKeys: some Sequence { + Self.scopeDescription.attributes.values + } } - #endif // FOUNDATION_FRAMEWORK diff --git a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift index c49567bb2..2c3345a48 100644 --- a/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift +++ b/Tests/FoundationEssentialsTests/AttributedString/AttributedStringTests.swift @@ -2427,6 +2427,22 @@ E { XCTAssertEqual(AttributedString(str[range], including: None.self), AttributedString("BC")) } + + func testScopeIterationAPI() { + struct TestScope : AttributeScope { + let testInt: AttributeScopes.TestAttributes.TestIntAttribute + let testBool: AttributeScopes.TestAttributes.TestBoolAttribute + } + + let testNames = TestScope.attributeKeys.map { $0.name }.sorted() + XCTAssertEqual(testNames, [AttributeScopes.TestAttributes.TestBoolAttribute.name, AttributeScopes.TestAttributes.TestIntAttribute.name].sorted()) + + struct EmptyScope : AttributeScope { + + } + var emptyIterator = EmptyScope.attributeKeys.makeIterator() + XCTAssertNil(emptyIterator.next()) + } #endif // FOUNDATION_FRAMEWORK func testAssignDifferentSubstring() {