diff --git a/Sources/MockoloFramework/Models/ParsedEntity.swift b/Sources/MockoloFramework/Models/ParsedEntity.swift index 58d516b7..170321cf 100644 --- a/Sources/MockoloFramework/Models/ParsedEntity.swift +++ b/Sources/MockoloFramework/Models/ParsedEntity.swift @@ -65,12 +65,17 @@ struct ResolvedEntity { func model() -> Model { let metadata = entity.metadata + // Combine protocol-level attributes with member-level attributes + let protocolLevelAttributes = + entity.entityNode.attributesDescription.isEmpty + ? [] : [entity.entityNode.attributesDescription] + let combinedAttributes = protocolLevelAttributes + attributes return NominalModel(selfType: .init(name: metadata?.nameOverride ?? (key + "Mock")), namespaces: entity.entityNode.namespaces, acl: entity.entityNode.accessLevel, declKindOfMockAnnotatedBaseType: entity.entityNode.declKind, declKind: inheritsActorProtocol ? .actor : .class, - attributes: attributes, + attributes: combinedAttributes, offset: entity.entityNode.offset, inheritedTypeName: (entity.metadata?.module?.withDot ?? "") + key, genericWhereConstraints: entity.entityNode.genericWhereConstraints, diff --git a/Tests/TestActor/FixtureActor.swift b/Tests/TestActor/FixtureActor.swift index 9224d39d..b6513476 100644 --- a/Tests/TestActor/FixtureActor.swift +++ b/Tests/TestActor/FixtureActor.swift @@ -100,6 +100,9 @@ init() { } } + @MainActor + /// @mockable + @available(iOS 18.0, *) class P1Mock: P1 { init() { } } diff --git a/Tests/TestSendable/FixtureSendable.swift b/Tests/TestSendable/FixtureSendable.swift index 59f128e4..61ba1165 100644 --- a/Tests/TestSendable/FixtureSendable.swift +++ b/Tests/TestSendable/FixtureSendable.swift @@ -208,4 +208,40 @@ } } } + +@Fixture enum availableSendableProtocol { + /// @mockable + @available(iOS 18.0, *) + public protocol Foo: Sendable { + func bar() -> String + } + + @Fixture(includesConcurrencyHelpers: true) + enum expected { + @available(iOS 18.0, *) + public final class FooMock: Foo, @unchecked Sendable { + public init() { } + + + private let barState = MockoloMutex(MockoloHandlerState String>()) + public var barCallCount: Int { + return barState.withLock(\.callCount) + } + public var barHandler: (@Sendable () -> String)? { + get { barState.withLock(\.handler) } + set { barState.withLock { $0.handler = newValue } } + } + public func bar() -> String { + let barHandler = barState.withLock { state in + state.callCount += 1 + return state.handler + } + if let barHandler = barHandler { + return barHandler() + } + return "" + } + } + } +} #endif diff --git a/Tests/TestSendable/SendableTests.swift b/Tests/TestSendable/SendableTests.swift index 4bd7f1a0..3130eadb 100644 --- a/Tests/TestSendable/SendableTests.swift +++ b/Tests/TestSendable/SendableTests.swift @@ -21,5 +21,10 @@ class SendableTests: MockoloTestCase { verify(srcContent: confirmedSendableProtocol._source, dstContent: confirmedSendableProtocol.expected._source) } + + func testAvailableSendableProtocol() { + verify(srcContent: availableSendableProtocol._source, + dstContent: availableSendableProtocol.expected._source) + } } #endif