From b7252d230b9b0644e142d2c49248194b1d6961ec Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Sun, 24 Mar 2024 16:00:08 +0900 Subject: [PATCH 1/6] Add an accessor macro example --- .../Accessor/EnvironmentValueMacro.swift | 36 +++++++++++++ .../MacroExamples/Implementation/Plugin.swift | 1 + .../Interface/AccessorMacros.swift | 19 +++++++ .../Playground/AccessorMacrosPlayground.swift | 32 ++++++++++++ .../MacroExamples/Playground/main.swift | 4 ++ .../Accessor/EnvironmentValueMacroTests.swift | 52 +++++++++++++++++++ 6 files changed, 144 insertions(+) create mode 100644 Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift create mode 100644 Examples/Sources/MacroExamples/Interface/AccessorMacros.swift create mode 100644 Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift create mode 100644 Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift diff --git a/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift b/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift new file mode 100644 index 00000000000..95fd77dba88 --- /dev/null +++ b/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxMacros + +public struct EnvironmentValueMacro: AccessorMacro { + public static func expansion( + of node: AttributeSyntax, + providingAccessorsOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [AccessorDeclSyntax] { + guard + case let .argumentList(arguments) = node.arguments, + let argument = arguments.first + else { return [] } + + return [ + """ + get { self[\(raw: argument.expression)] } + """, + """ + set { self[\(raw: argument.expression)] = newValue } + """, + ] + } +} diff --git a/Examples/Sources/MacroExamples/Implementation/Plugin.swift b/Examples/Sources/MacroExamples/Implementation/Plugin.swift index e5960e80712..cd157e62baf 100644 --- a/Examples/Sources/MacroExamples/Implementation/Plugin.swift +++ b/Examples/Sources/MacroExamples/Implementation/Plugin.swift @@ -26,6 +26,7 @@ struct MyPlugin: CompilerPlugin { DefaultFatalErrorImplementationMacro.self, DictionaryStorageMacro.self, DictionaryStoragePropertyMacro.self, + EnvironmentValueMacro.self, EquatableExtensionMacro.self, FontLiteralMacro.self, FuncUniqueMacro.self, diff --git a/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift new file mode 100644 index 00000000000..1834dc7e98c --- /dev/null +++ b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftUI + +// MARK: - EnvironmentValue Accessor + +@attached(accessor) +public macro EnvironmentValue(for key: any EnvironmentKey.Type) = + #externalMacro(module: "MacroExamplesImplementation", type: "EnvironmentValueMacro") diff --git a/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift b/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift new file mode 100644 index 00000000000..429e66c91e9 --- /dev/null +++ b/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// MARK: - EnvironmentValue Accessor + +import MacroExamplesInterface +import SwiftUI + +private struct MyEnvironmentKey: EnvironmentKey { + static let defaultValue: String = "Default value" +} + +extension EnvironmentValues { + @EnvironmentValue(for: MyEnvironmentKey.self) + var myCustomValue: String +} + +func runEnvironmentValueAccessorMacroPlayground() { + var environmentValues = EnvironmentValues() + print("Default myCustomValue: \(environmentValues.myCustomValue)") + environmentValues.myCustomValue = "New value" + print("New myCustomValue: \(environmentValues.myCustomValue)") +} diff --git a/Examples/Sources/MacroExamples/Playground/main.swift b/Examples/Sources/MacroExamples/Playground/main.swift index d9af26d3e0e..9f861361c24 100644 --- a/Examples/Sources/MacroExamples/Playground/main.swift +++ b/Examples/Sources/MacroExamples/Playground/main.swift @@ -47,3 +47,7 @@ runMemberMacrosPlayground() // MARK: - Peer Macros runPeerMacrosPlayground() + +// MARKL - Accessor Macros + +runEnvironmentValueAccessorMacroPlayground() diff --git a/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift b/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift new file mode 100644 index 00000000000..a32a9eae679 --- /dev/null +++ b/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import MacroExamplesImplementation +import SwiftSyntaxMacros +import SwiftSyntaxMacrosTestSupport +import XCTest + +final class EnvironmentValueMacroMacroTests: XCTestCase { + private let macros = ["EnvironmentValue": EnvironmentValueMacro.self] + + func testEnvironmentValue() { + assertMacroExpansion( + """ + private struct MyEnvironmentKey: EnvironmentKey { + static let defaultValue: String = "Default value" + } + + extension EnvironmentValues { + @EnvironmentValue(for: MyEnvironmentKey.self) + var myCustomValue: String + } + """, + expandedSource: """ + private struct MyEnvironmentKey: EnvironmentKey { + static let defaultValue: String = "Default value" + } + + extension EnvironmentValues { + var myCustomValue: String { + get { + self[MyEnvironmentKey.self] + } + set { + self[MyEnvironmentKey.self] = newValue + } + } + } + """, + macros: macros + ) + } +} From 441be203b5d1f4b52fbb5427dae4c54490b35d8e Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Mon, 25 Mar 2024 08:06:49 +0900 Subject: [PATCH 2/6] Add a document comment --- Examples/Sources/MacroExamples/Interface/AccessorMacros.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift index 1834dc7e98c..55cabbd2302 100644 --- a/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift +++ b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift @@ -14,6 +14,7 @@ import SwiftUI // MARK: - EnvironmentValue Accessor +/// Adds getter / setter to an attached environment value with specified EnvironmentKey @attached(accessor) public macro EnvironmentValue(for key: any EnvironmentKey.Type) = #externalMacro(module: "MacroExamplesImplementation", type: "EnvironmentValueMacro") From a283c965a0049aeefb68b79e37119451a7178bc2 Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:02:55 +0900 Subject: [PATCH 3/6] Remove unnecessary raw interpolations --- .../Implementation/Accessor/EnvironmentValueMacro.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift b/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift index 95fd77dba88..01510a12726 100644 --- a/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/Accessor/EnvironmentValueMacro.swift @@ -26,10 +26,10 @@ public struct EnvironmentValueMacro: AccessorMacro { return [ """ - get { self[\(raw: argument.expression)] } + get { self[\(argument.expression)] } """, """ - set { self[\(raw: argument.expression)] = newValue } + set { self[\(argument.expression)] = newValue } """, ] } From 74a3d68cbc14c55cbe4179ace996f07e279b5238 Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:03:59 +0900 Subject: [PATCH 4/6] Remove unnecessary EnvironmentKey --- .../Accessor/EnvironmentValueMacroTests.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift b/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift index a32a9eae679..73749476ebb 100644 --- a/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift +++ b/Examples/Tests/MacroExamples/Implementation/Accessor/EnvironmentValueMacroTests.swift @@ -21,20 +21,12 @@ final class EnvironmentValueMacroMacroTests: XCTestCase { func testEnvironmentValue() { assertMacroExpansion( """ - private struct MyEnvironmentKey: EnvironmentKey { - static let defaultValue: String = "Default value" - } - extension EnvironmentValues { @EnvironmentValue(for: MyEnvironmentKey.self) var myCustomValue: String } """, expandedSource: """ - private struct MyEnvironmentKey: EnvironmentKey { - static let defaultValue: String = "Default value" - } - extension EnvironmentValues { var myCustomValue: String { get { From aaefc0e4f860be9933e520d42710750b82b4be39 Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:04:27 +0900 Subject: [PATCH 5/6] Fix typo --- Examples/Sources/MacroExamples/Playground/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/Sources/MacroExamples/Playground/main.swift b/Examples/Sources/MacroExamples/Playground/main.swift index 9f861361c24..e1a0812ded7 100644 --- a/Examples/Sources/MacroExamples/Playground/main.swift +++ b/Examples/Sources/MacroExamples/Playground/main.swift @@ -48,6 +48,6 @@ runMemberMacrosPlayground() runPeerMacrosPlayground() -// MARKL - Accessor Macros +// MARK: - Accessor Macros runEnvironmentValueAccessorMacroPlayground() From b795cd867948fdefedd7c35958f84ab4a762e767 Mon Sep 17 00:00:00 2001 From: rockname <8536870+rockname@users.noreply.github.com> Date: Tue, 26 Mar 2024 08:11:03 +0900 Subject: [PATCH 6/6] Add '#if canImport(SwiftUI)' --- .../Sources/MacroExamples/Interface/AccessorMacros.swift | 4 ++++ .../MacroExamples/Playground/AccessorMacrosPlayground.swift | 5 +++++ Examples/Sources/MacroExamples/Playground/main.swift | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift index 55cabbd2302..17b6f16244e 100644 --- a/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift +++ b/Examples/Sources/MacroExamples/Interface/AccessorMacros.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#if canImport(SwiftUI) + import SwiftUI // MARK: - EnvironmentValue Accessor @@ -18,3 +20,5 @@ import SwiftUI @attached(accessor) public macro EnvironmentValue(for key: any EnvironmentKey.Type) = #externalMacro(module: "MacroExamplesImplementation", type: "EnvironmentValueMacro") + +#endif diff --git a/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift b/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift index 429e66c91e9..e100945a573 100644 --- a/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift +++ b/Examples/Sources/MacroExamples/Playground/AccessorMacrosPlayground.swift @@ -13,6 +13,9 @@ // MARK: - EnvironmentValue Accessor import MacroExamplesInterface + +#if canImport(SwiftUI) + import SwiftUI private struct MyEnvironmentKey: EnvironmentKey { @@ -30,3 +33,5 @@ func runEnvironmentValueAccessorMacroPlayground() { environmentValues.myCustomValue = "New value" print("New myCustomValue: \(environmentValues.myCustomValue)") } + +#endif diff --git a/Examples/Sources/MacroExamples/Playground/main.swift b/Examples/Sources/MacroExamples/Playground/main.swift index e1a0812ded7..674b9b9b745 100644 --- a/Examples/Sources/MacroExamples/Playground/main.swift +++ b/Examples/Sources/MacroExamples/Playground/main.swift @@ -50,4 +50,8 @@ runPeerMacrosPlayground() // MARK: - Accessor Macros +#if canImport(SwiftUI) + runEnvironmentValueAccessorMacroPlayground() + +#endif