diff --git a/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilder.swift b/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilder.swift index 5b1d20e..18710c0 100644 --- a/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilder.swift +++ b/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilder.swift @@ -26,15 +26,13 @@ extension DeclBuilder { ) } - public var inheritedGlobalActorIsolation: AttributeSyntax? { - let globalActor: AttributeSyntax? = switch settings.globalActorIsolationPreference { - case .nonisolated: - nil - case let .isolated(globalActor): - "@\(globalActor)" - case .none: - basicDeclaration.globalActor?.trimmed + public var inheritedGlobalActorIsolation: GlobalActorIsolation? { + if let preferred = settings.preferredGlobalActorIsolation { + return preferred } - return globalActor?.withTrailingSpace + if let inferredType = basicDeclaration.globalActor?.attributeName.trimmed { + return .isolated(trimmedType: inferredType) + } + return .nonisolated } } diff --git a/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilderSettings.swift b/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilderSettings.swift index c157be7..1c81b02 100644 --- a/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilderSettings.swift +++ b/Sources/PrincipleMacros/Builders/Declarations/Common/DeclBuilderSettings.swift @@ -11,14 +11,14 @@ import SwiftSyntax public struct DeclBuilderSettings { public var accessControlLevel: AccessControlLevel - public var globalActorIsolationPreference: GlobalActorIsolationPreference? + public var preferredGlobalActorIsolation: GlobalActorIsolation? public init( accessControlLevel: AccessControlLevel, - globalActorIsolationPreference: GlobalActorIsolationPreference? = nil + preferredGlobalActorIsolation: GlobalActorIsolation? = nil ) { self.accessControlLevel = accessControlLevel - self.globalActorIsolationPreference = globalActorIsolationPreference + self.preferredGlobalActorIsolation = preferredGlobalActorIsolation } } diff --git a/Sources/PrincipleMacros/Parameters/ParameterExtractor.swift b/Sources/PrincipleMacros/Parameters/ParameterExtractor.swift index f86a826..e17ad0a 100644 --- a/Sources/PrincipleMacros/Parameters/ParameterExtractor.swift +++ b/Sources/PrincipleMacros/Parameters/ParameterExtractor.swift @@ -64,9 +64,9 @@ public struct ParameterExtractor { return rawString } - public func globalActorIsolationPreference( + public func preferredGlobalActorIsolation( withLabel label: TokenSyntax? - ) throws -> GlobalActorIsolationPreference? { + ) throws -> GlobalActorIsolation? { guard let expression = expression(withLabel: label) else { return nil } @@ -77,8 +77,8 @@ public struct ParameterExtractor { if let memberAccessExpression = MemberAccessExprSyntax(expression), memberAccessExpression.declName.baseName.tokenKind == .keyword(.self), - let baseType = memberAccessExpression.base { - return .isolated("\(baseType)") + let explicitType = memberAccessExpression.base?.trimmed { + return .isolated(trimmedType: "\(explicitType)") } throw ParameterExtractionError.unexpectedSyntaxType diff --git a/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolation.swift b/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolation.swift new file mode 100644 index 0000000..6c116a8 --- /dev/null +++ b/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolation.swift @@ -0,0 +1,33 @@ +// +// GlobalActorIsolation.swift +// PrincipleMacros +// +// Created by Kamil Strzelecki on 18/08/2025. +// Copyright © 2025 Kamil Strzelecki. All rights reserved. +// + +import SwiftSyntax + +public enum GlobalActorIsolation: Hashable { + + case nonisolated + case isolated(trimmedType: TypeSyntax) + + public var trimmedType: TypeSyntax? { + switch self { + case let .isolated(type): + type + case .nonisolated: + nil + } + } + + public var trimmedAttribute: AttributeSyntax? { + guard let trimmedType else { + return nil + } + return AttributeSyntax( + attributeName: trimmedType + ) + } +} diff --git a/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolationPreference.swift b/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolationPreference.swift deleted file mode 100644 index d5ea051..0000000 --- a/Sources/PrincipleMacros/Syntax/Helpers/GlobalActorIsolationPreference.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// GlobalActorIsolationPreference.swift -// PrincipleMacros -// -// Created by Kamil Strzelecki on 18/08/2025. -// Copyright © 2025 Kamil Strzelecki. All rights reserved. -// - -import SwiftSyntax - -public enum GlobalActorIsolationPreference: Hashable { - - case nonisolated - case isolated(TypeSyntax) -} diff --git a/Tests/PrincipleMacrosTests/Parameters/ParameterExtractorTests.swift b/Tests/PrincipleMacrosTests/Parameters/ParameterExtractorTests.swift index db266df..61dd125 100644 --- a/Tests/PrincipleMacrosTests/Parameters/ParameterExtractorTests.swift +++ b/Tests/PrincipleMacrosTests/Parameters/ParameterExtractorTests.swift @@ -46,16 +46,14 @@ extension ParameterExtractorTests { func testTrailingClosureExtraction() throws { let extractor = try makeExtractor(from: "#MyMacro { _ in }") let extracted = try extractor.trailingClosure(withLabel: "operation") - let expected: ExprSyntax = "{ _ in }" - #expect(extracted?.description == expected.description) + #expect(extracted?.description == "{ _ in }") } @Test func testTrailingClosureReferenceExtraction() throws { let extractor = try makeExtractor(from: "#MyMacro(operation: perform)") let extracted = try extractor.trailingClosure(withLabel: "operation") - let expected: ExprSyntax = "perform" - #expect(extracted?.description == expected.description) + #expect(extracted?.description == "perform") } } @@ -80,16 +78,16 @@ extension ParameterExtractorTests { extension ParameterExtractorTests { @Test - func testMissingGlobalActorPreferenceExtraction() throws { + func testMissingPreferredGlobalActorExtraction() throws { let extractor = try makeExtractor(from: "#MyMacro()") - let extracted = try extractor.globalActorIsolationPreference(withLabel: "isolation") + let extracted = try extractor.preferredGlobalActorIsolation(withLabel: "isolation") #expect(extracted == nil) } @Test - func testNonisolatedGlobalActorPreferenceExtraction() throws { + func testNonisolatedPreferredGlobalActorExtraction() throws { let extractor = try makeExtractor(from: "#MyMacro(isolation: nil)") - let extracted = try extractor.globalActorIsolationPreference(withLabel: "isolation") + let extracted = try extractor.preferredGlobalActorIsolation(withLabel: "isolation") #expect(extracted == .nonisolated) } @@ -99,23 +97,17 @@ extension ParameterExtractorTests { "SomeType.SomeActor" ] ) - func testIsolatedGlobalActorPreferenceExtraction(isolation: String) throws { + func testIsolatedPreferredGlobalActorExtraction(isolation: String) throws { let extractor = try makeExtractor(from: "#MyMacro(isolation: \(raw: isolation).self)") - let extracted = try extractor.globalActorIsolationPreference(withLabel: "isolation") - - switch extracted { - case let .isolated(globalActor): - #expect(globalActor.description == isolation) - default: - Issue.record() - } + let extracted = try extractor.preferredGlobalActorIsolation(withLabel: "isolation") + #expect(extracted?.attribute?.description == "@\(isolation)") } @Test - func testUnexpectedSyntaxWhenPerformingGlobalActorPreferenceExtraction() throws { + func testUnexpectedSyntaxWhenPerformingPreferredGlobalActorExtraction() throws { let extractor = try makeExtractor(from: #"#MyMacro(isolation: MainActor.Type)"#) #expect(throws: ParameterExtractionError.unexpectedSyntaxType) { - try extractor.globalActorIsolationPreference(withLabel: "isolation") + try extractor.preferredGlobalActorIsolation(withLabel: "isolation") } } }