Skip to content

Commit 02adade

Browse files
committed
Extend MacroExpansionContext with a build-configuration property
The (optional) build configuration provides information about the context in which the macro-generated code will be compiled. It allows one to inspect various aspects of the configuration, including available attributes and features, the target architecture/OS/environment/etc., and any custom settings passed via `-D` on the command line.
1 parent 315794d commit 02adade

File tree

9 files changed

+90
-9
lines changed

9 files changed

+90
-9
lines changed

Package.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,13 @@ let package = Package(
275275

276276
.target(
277277
name: "SwiftSyntaxMacros",
278-
dependencies: ["SwiftDiagnostics", "SwiftParser", "SwiftSyntax", "SwiftSyntaxBuilder"],
278+
dependencies: [
279+
"SwiftDiagnostics",
280+
"SwiftIfConfig",
281+
"SwiftParser",
282+
"SwiftSyntax",
283+
"SwiftSyntaxBuilder",
284+
],
279285
exclude: ["CMakeLists.txt"]
280286
),
281287

Sources/SwiftCompilerPluginMessageHandling/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ target_link_swift_syntax_libraries(SwiftCompilerPluginMessageHandling PUBLIC
2525
SwiftSyntax
2626
SwiftBasicFormat
2727
SwiftDiagnostics
28+
SwiftIfConfig
2829
SwiftParser
2930
SwiftSyntaxMacros
3031
SwiftSyntaxMacroExpansion

Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import _SwiftSyntaxCShims
2121
#endif
2222

2323
#if compiler(>=6)
24+
internal import SwiftIfConfig
2425
public import SwiftSyntaxMacros
2526
#else
27+
import SwiftIfConfig
2628
import SwiftSyntaxMacros
2729
#endif
2830

@@ -189,12 +191,25 @@ public class PluginProviderMessageHandler<Provider: PluginProvider>: PluginMessa
189191
let macroRole,
190192
let discriminator,
191193
let expandingSyntax,
192-
let lexicalContext
194+
let lexicalContext,
195+
let staticBuildConfigurationString
193196
):
197+
// Decode the static build configuration.
198+
let staticBuildConfiguration: StaticBuildConfiguration?
199+
if let staticBuildConfigurationString {
200+
var mutableConfigurationString = staticBuildConfigurationString
201+
staticBuildConfiguration = mutableConfigurationString.withUTF8 {
202+
try? JSON.decode(StaticBuildConfiguration.self, from: $0)
203+
}
204+
} else {
205+
staticBuildConfiguration = nil
206+
}
207+
194208
return expandFreestandingMacro(
195209
macro: macro,
196210
macroRole: macroRole,
197211
discriminator: discriminator,
212+
staticBuildConfiguration: staticBuildConfiguration,
198213
expandingSyntax: expandingSyntax,
199214
lexicalContext: lexicalContext
200215
)
@@ -208,12 +223,25 @@ public class PluginProviderMessageHandler<Provider: PluginProvider>: PluginMessa
208223
let parentDeclSyntax,
209224
let extendedTypeSyntax,
210225
let conformanceListSyntax,
211-
let lexicalContext
226+
let lexicalContext,
227+
let staticBuildConfigurationString
212228
):
229+
// Decode the static build configuration.
230+
let staticBuildConfiguration: StaticBuildConfiguration?
231+
if let staticBuildConfigurationString {
232+
var mutableConfigurationString = staticBuildConfigurationString
233+
staticBuildConfiguration = mutableConfigurationString.withUTF8 {
234+
try? JSON.decode(StaticBuildConfiguration.self, from: $0)
235+
}
236+
} else {
237+
staticBuildConfiguration = nil
238+
}
239+
213240
return expandAttachedMacro(
214241
macro: macro,
215242
macroRole: macroRole,
216243
discriminator: discriminator,
244+
staticBuildConfiguration: staticBuildConfiguration,
217245
attributeSyntax: attributeSyntax,
218246
declSyntax: declSyntax,
219247
parentDeclSyntax: parentDeclSyntax,

Sources/SwiftCompilerPluginMessageHandling/Macros.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
#if compiler(>=6)
1414
internal import SwiftBasicFormat
1515
internal import SwiftDiagnostics
16+
internal import SwiftIfConfig
1617
internal import SwiftOperators
1718
internal import SwiftSyntax
1819
@_spi(MacroExpansion) @_spi(ExperimentalLanguageFeature) internal import SwiftSyntaxMacroExpansion
1920
@_spi(ExperimentalLanguageFeature) internal import SwiftSyntaxMacros
2021
#else
2122
import SwiftBasicFormat
2223
import SwiftDiagnostics
24+
import SwiftIfConfig
2325
import SwiftOperators
2426
import SwiftSyntax
2527
@_spi(MacroExpansion) @_spi(ExperimentalLanguageFeature) import SwiftSyntaxMacroExpansion
@@ -53,6 +55,7 @@ extension PluginProviderMessageHandler {
5355
macro: PluginMessage.MacroReference,
5456
macroRole pluginMacroRole: PluginMessage.MacroRole?,
5557
discriminator: String,
58+
staticBuildConfiguration: StaticBuildConfiguration?,
5659
expandingSyntax: PluginMessage.Syntax,
5760
lexicalContext: [PluginMessage.Syntax]?
5861
) -> PluginToHostMessage {
@@ -67,7 +70,8 @@ extension PluginProviderMessageHandler {
6770
operatorTable: .standardOperators,
6871
fallbackSyntax: syntax
6972
),
70-
expansionDiscriminator: discriminator
73+
expansionDiscriminator: discriminator,
74+
staticBuildConfiguration: staticBuildConfiguration
7175
)
7276

7377
let expandedSource: String?
@@ -113,6 +117,7 @@ extension PluginProviderMessageHandler {
113117
macro: PluginMessage.MacroReference,
114118
macroRole: PluginMessage.MacroRole,
115119
discriminator: String,
120+
staticBuildConfiguration: StaticBuildConfiguration?,
116121
attributeSyntax: PluginMessage.Syntax,
117122
declSyntax: PluginMessage.Syntax,
118123
parentDeclSyntax: PluginMessage.Syntax?,
@@ -143,7 +148,8 @@ extension PluginProviderMessageHandler {
143148
operatorTable: .standardOperators,
144149
fallbackSyntax: declarationNode
145150
),
146-
expansionDiscriminator: discriminator
151+
expansionDiscriminator: discriminator,
152+
staticBuildConfiguration: staticBuildConfiguration
147153
)
148154

149155
// TODO: Make this a 'String?' and remove non-'hasExpandMacroResult' branches.

Sources/SwiftCompilerPluginMessageHandling/PluginMacroExpansionContext.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212

1313
#if compiler(>=6)
1414
internal import SwiftDiagnostics
15+
internal import SwiftIfConfig
1516
internal import SwiftOperators
1617
internal import SwiftParser
1718
internal import SwiftSyntax
1819
internal import SwiftSyntaxMacros
1920
#else
2021
import SwiftDiagnostics
22+
import SwiftIfConfig
2123
import SwiftOperators
2224
import SwiftParser
2325
import SwiftSyntax
@@ -262,6 +264,10 @@ class PluginMacroExpansionContext {
262264
/// to produce unique names.
263265
private var expansionDiscriminator: String
264266

267+
/// The static build configuration, if any, that will be used for the
268+
/// macro-expanded code.
269+
private var staticBuildConfiguration: StaticBuildConfiguration?
270+
265271
/// Counter for each of the uniqued names.
266272
///
267273
/// Used in conjunction with `expansionDiscriminator`.
@@ -271,10 +277,16 @@ class PluginMacroExpansionContext {
271277
/// macro.
272278
internal private(set) var diagnostics: [Diagnostic] = []
273279

274-
init(sourceManager: SourceManager, lexicalContext: [Syntax], expansionDiscriminator: String = "") {
280+
init(
281+
sourceManager: SourceManager,
282+
lexicalContext: [Syntax],
283+
expansionDiscriminator: String = "",
284+
staticBuildConfiguration: StaticBuildConfiguration?
285+
) {
275286
self.sourceManager = sourceManager
276287
self.lexicalContext = lexicalContext
277288
self.expansionDiscriminator = expansionDiscriminator
289+
self.staticBuildConfiguration = staticBuildConfiguration
278290
}
279291
}
280292

@@ -321,4 +333,8 @@ extension PluginMacroExpansionContext: MacroExpansionContext {
321333
}
322334
return AbstractSourceLocation(location)
323335
}
336+
337+
public var buildConfiguration: (any BuildConfiguration)? {
338+
staticBuildConfiguration
339+
}
324340
}

Sources/SwiftCompilerPluginMessageHandling/PluginMessages.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public enum HostToPluginMessage: Codable {
2525
macroRole: PluginMessage.MacroRole? = nil,
2626
discriminator: String,
2727
syntax: PluginMessage.Syntax,
28-
lexicalContext: [PluginMessage.Syntax]? = nil
28+
lexicalContext: [PluginMessage.Syntax]? = nil,
29+
staticBuildConfiguration: String? = nil
2930
)
3031

3132
/// Expand an '@attached' macro.
@@ -38,7 +39,8 @@ public enum HostToPluginMessage: Codable {
3839
parentDeclSyntax: PluginMessage.Syntax?,
3940
extendedTypeSyntax: PluginMessage.Syntax?,
4041
conformanceListSyntax: PluginMessage.Syntax?,
41-
lexicalContext: [PluginMessage.Syntax]? = nil
42+
lexicalContext: [PluginMessage.Syntax]? = nil,
43+
staticBuildConfiguration: String? = nil
4244
)
4345

4446
/// Optionally implemented message to load a dynamic link library.

Sources/SwiftSyntaxMacroExpansion/BasicMacroExpansionContext.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313
#if compiler(>=6)
1414
public import SwiftDiagnostics
15+
public import SwiftIfConfig
1516
internal import SwiftOperators
1617
public import SwiftSyntax
1718
public import SwiftSyntaxMacros
1819
#else
1920
import SwiftDiagnostics
21+
import SwiftIfConfig
2022
import SwiftOperators
2123
import SwiftSyntax
2224
import SwiftSyntaxMacros
@@ -62,6 +64,9 @@ public class BasicMacroExpansionContext {
6264
///
6365
/// Used in conjunction with `expansionDiscriminator`.
6466
var uniqueNames: [String: Int] = [:]
67+
68+
/// The build configuration that will be applied to the expanded code.
69+
var buildConfiguration: (any BuildConfiguration)? = nil
6570
}
6671

6772
/// State shared by different instances of the macro expansion context,
@@ -82,12 +87,14 @@ public class BasicMacroExpansionContext {
8287
public init(
8388
lexicalContext: [Syntax] = [],
8489
expansionDiscriminator: String = "__macro_local_",
85-
sourceFiles: [SourceFileSyntax: KnownSourceFile] = [:]
90+
sourceFiles: [SourceFileSyntax: KnownSourceFile] = [:],
91+
buildConfiguration: (any BuildConfiguration)? = nil
8692
) {
8793
self.sharedState = SharedState()
8894
self.lexicalContext = lexicalContext
8995
self.expansionDiscriminator = expansionDiscriminator
9096
self.sharedState.sourceFiles = sourceFiles
97+
self.sharedState.buildConfiguration = buildConfiguration
9198
}
9299

93100
/// Create a new macro evaluation context that shares most of its global

Sources/SwiftSyntaxMacros/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ add_swift_syntax_library(SwiftSyntaxMacros
2929
)
3030

3131
target_link_swift_syntax_libraries(SwiftSyntaxMacros PUBLIC
32+
SwiftIfConfig
3233
SwiftSyntaxBuilder
3334
)

Sources/SwiftSyntaxMacros/MacroExpansionContext.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
#if compiler(>=6)
1414
public import SwiftDiagnostics
15+
public import SwiftIfConfig
1516
public import SwiftSyntax
1617
import SwiftSyntaxBuilder
1718
#else
1819
import SwiftDiagnostics
20+
import SwiftIfConfig
1921
import SwiftSyntax
2022
import SwiftSyntaxBuilder
2123
#endif
@@ -70,6 +72,13 @@ public protocol MacroExpansionContext: AnyObject {
7072
/// This array can be empty if there is no context, for example when a
7173
/// freestanding macro is used at file scope.
7274
var lexicalContext: [Syntax] { get }
75+
76+
/// Returns the build configuration that will be used with the generated
77+
/// source code. Macro implementations can use this information to determine
78+
/// the context into which they are generating code.
79+
///
80+
/// When the build configuration is not known, this returns nil.
81+
var buildConfiguration: (any BuildConfiguration)? { get }
7382
}
7483

7584
extension MacroExpansionContext {
@@ -187,3 +196,8 @@ public enum SourceLocationFilePathMode {
187196
/// e.g., `/home/taylor/alison.swift`.
188197
case filePath
189198
}
199+
200+
extension MacroExpansionContext {
201+
/// Default implementation that produces no build configuration.
202+
public var buildConfiguration: (any BuildConfiguration)? { nil }
203+
}

0 commit comments

Comments
 (0)