Skip to content

Commit 334d6d2

Browse files
committed
Add swift-syntax 510 support; matrix testing for swift-syntax versions
- Implement matrix strategy for macOS job to test against multiple versions of swift-syntax - Use SWIFT_SYNTAX_VERSION environment variable to dictate swift-syntax version per test run - Maintain existing setup for Linux CI (only test "natural" `Package.swift` swift-syntax version), but update to use `swift-actions/setup-swift` and Swift 5.10.
1 parent 84f14bc commit 334d6d2

File tree

12 files changed

+323
-101
lines changed

12 files changed

+323
-101
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@ jobs:
1717
macos:
1818
name: macOS
1919
runs-on: macos-13
20+
strategy:
21+
matrix:
22+
swift-syntax-version: ['509.0.0..<510.0.0', '510.0.0..<511.0.0']
23+
2024
steps:
2125
- uses: actions/checkout@v4
2226
- name: Select Xcode 15
2327
run: sudo xcode-select -s /Applications/Xcode_15.0.app
28+
- name: Set SWIFT_SYNTAX_VERSION environment variable
29+
run: echo "SWIFT_SYNTAX_VERSION=${{ matrix.swift-syntax-version }}" >> $GITHUB_ENV
30+
- name: Resolve Dependencies
31+
run: swift package resolve
2432
- name: Run tests
2533
run: swift test
2634

@@ -29,9 +37,9 @@ jobs:
2937
runs-on: ubuntu-latest
3038
steps:
3139
- name: Install Swift
32-
uses: slashmo/install-swift@v0.4.0
40+
uses: swift-actions/setup-swift@v2
3341
with:
34-
version: 5.9
42+
swift-version: "5.10"
3543
- uses: actions/checkout@v4
3644
- name: Run tests
3745
run: swift test

Package.resolved

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
"kind" : "remoteSourceControl",
66
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
77
"state" : {
8-
"revision" : "59b663f68e69f27a87b45de48cb63264b8194605",
9-
"version" : "1.15.1"
8+
"revision" : "625ccca8570773dd84a34ee51a81aa2bc5a4f97a",
9+
"version" : "1.16.0"
1010
}
1111
},
1212
{
1313
"identity" : "swift-syntax",
1414
"kind" : "remoteSourceControl",
15-
"location" : "https://github.com/apple/swift-syntax.git",
15+
"location" : "https://github.com/apple/swift-syntax",
1616
"state" : {
17-
"revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036",
18-
"version" : "509.0.2"
17+
"revision" : "fa8f95c2d536d6620cc2f504ebe8a6167c9fc2dd",
18+
"version" : "510.0.1"
1919
}
2020
}
2121
],

Package.swift

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// swift-tools-version: 5.9
22

33
import CompilerPluginSupport
4+
import Foundation
45
import PackageDescription
56

67
let package = Package(
@@ -23,7 +24,13 @@ let package = Package(
2324
],
2425
dependencies: [
2526
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.15.0"),
26-
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0"),
27+
//.conditionalPackage(url: "https://github.com/apple/swift-syntax", envVar: "SWIFT_SYNTAX_VERSION", default: "509.0.0..<510.0.0")
28+
//.conditionalPackage(url: "https://github.com/apple/swift-syntax", envVar: "SWIFT_SYNTAX_VERSION", default: "510.0.0..<511.0.0")
29+
.conditionalPackage(
30+
url: "https://github.com/apple/swift-syntax",
31+
envVar: "SWIFT_SYNTAX_VERSION",
32+
default: "509.0.0..<511.0.0"
33+
),
2734
],
2835
targets: [
2936
.macro(
@@ -68,3 +75,55 @@ let package = Package(
6875
),
6976
]
7077
)
78+
79+
extension Package.Dependency {
80+
/// Creates a dependency based on an environment variable or a default version range.
81+
///
82+
/// This function allows dynamically setting the version range of a package dependency via an environment variable.
83+
/// If the environment variable is not set, it falls back to a specified default version range.
84+
///
85+
/// - Parameters:
86+
/// - url: The URL of the package repository.
87+
/// - envVar: The name of the environment variable that contains the version range.
88+
/// - versionExpression: The default version range in case the environment variable is not set.
89+
/// Example format: `"509.0.0..<511.0.0"` or `"509.0.0...510.0.0"`.
90+
/// - Returns: A `Package.Dependency` configured with the specified or default version range.
91+
/// - Throws: A fatal error if the version expression format is invalid or the range operator is unsupported.
92+
///
93+
static func conditionalPackage(
94+
url: String,
95+
envVar: String,
96+
default versionExpression: String
97+
) -> Package.Dependency {
98+
let versionRangeString = ProcessInfo.processInfo.environment[envVar] ?? versionExpression
99+
let (lower, op, upper) = parseVersionExpression(from: versionRangeString)
100+
if op == "..<" {
101+
return .package(url: url, lower..<upper)
102+
} else if op == "..." {
103+
return .package(url: url, lower...upper)
104+
} else {
105+
fatalError("Unsupported version range operator: \(op)")
106+
}
107+
}
108+
109+
private static func parseVersionExpression(
110+
from expression: String
111+
) -> (Version, String, Version) {
112+
let rangeOperators = ["..<", "..."]
113+
for op in rangeOperators {
114+
if expression.contains(op) {
115+
let parts = expression.split(separator: op, maxSplits: 1, omittingEmptySubsequences: true)
116+
.map(String.init)
117+
guard
118+
parts.count == 2,
119+
let lower = Version(parts[0]),
120+
let upper = Version(parts[1])
121+
else {
122+
fatalError("Invalid version expression format: \(expression)")
123+
}
124+
return (lower, op, upper)
125+
}
126+
}
127+
fatalError("No valid range operator found in expression: \(expression)")
128+
}
129+
}

Sources/MemberwiseInitMacros/Macros/Support/ExprTypeInference.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ extension ExprSyntax {
256256
else { return nil }
257257
return .tuple(elementTypes)
258258

259+
#if canImport(SwiftSyntax510)
260+
case .thenStmt:
261+
return nil
262+
#endif
263+
259264
case .token, .accessorBlock, .accessorDeclList, .accessorDecl, .accessorEffectSpecifiers,
260265
.accessorParameters, .actorDecl, .arrayElementList, .arrayElement, .arrayType, .arrowExpr,
261266
.assignmentExpr, .associatedTypeDecl, .attributeList, .attribute, .attributedType,

Tests/MacroTestingTests/DictionaryStorageMacroTests.swift

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,73 @@ final class DictionaryStorageMacroTests: BaseTestCase {
1414
}
1515

1616
func testExpansionConvertsStoredProperties() {
17-
assertMacro {
18-
"""
19-
@DictionaryStorage
20-
struct Point {
21-
var x: Int = 1
22-
var y: Int = 2
23-
}
24-
"""
25-
} expansion: {
26-
"""
27-
struct Point {
28-
var x: Int = 1 {
29-
get {
30-
_storage["x", default: 1] as! Int
17+
#if canImport(SwiftSyntax510)
18+
assertMacro {
19+
"""
20+
@DictionaryStorage
21+
struct Point {
22+
var x: Int = 1
23+
var y: Int = 2
24+
}
25+
"""
26+
} expansion: {
27+
"""
28+
struct Point {
29+
var x: Int {
30+
get {
31+
_storage["x", default: 1] as! Int
32+
}
33+
set {
34+
_storage["x"] = newValue
35+
}
3136
}
32-
set {
33-
_storage["x"] = newValue
37+
var y: Int {
38+
get {
39+
_storage["y", default: 2] as! Int
40+
}
41+
set {
42+
_storage["y"] = newValue
43+
}
3444
}
45+
46+
var _storage: [String: Any] = [:]
47+
}
48+
"""
49+
}
50+
#elseif canImport(SwiftSyntax509)
51+
assertMacro {
52+
"""
53+
@DictionaryStorage
54+
struct Point {
55+
var x: Int = 1
56+
var y: Int = 2
3557
}
36-
var y: Int = 2 {
37-
get {
38-
_storage["y", default: 2] as! Int
58+
"""
59+
} expansion: {
60+
"""
61+
struct Point {
62+
var x: Int = 1 {
63+
get {
64+
_storage["x", default: 1] as! Int
65+
}
66+
set {
67+
_storage["x"] = newValue
68+
}
3969
}
40-
set {
41-
_storage["y"] = newValue
70+
var y: Int = 2 {
71+
get {
72+
_storage["y", default: 2] as! Int
73+
}
74+
set {
75+
_storage["y"] = newValue
76+
}
4277
}
43-
}
4478
45-
var _storage: [String: Any] = [:]
79+
var _storage: [String: Any] = [:]
80+
}
81+
"""
4682
}
47-
"""
48-
}
83+
#endif
4984
}
5085

5186
func testExpansionWithoutInitializersEmitsError() {

Tests/MacroTestingTests/MacroExamples/AddBlocker.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,6 @@ public struct AddBlocker: ExpressionMacro {
101101
context.diagnose(diag)
102102
}
103103

104-
return result.asProtocol(FreestandingMacroExpansionSyntax.self)!.argumentList.first!.expression
104+
return result.asProtocol(FreestandingMacroExpansionSyntax.self)!.arguments.first!.expression
105105
}
106106
}

Tests/MacroTestingTests/MacroExamples/FontLiteralMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public enum FontLiteralMacro: ExpressionMacro {
2222
in context: some MacroExpansionContext
2323
) throws -> ExprSyntax {
2424
let argList = replaceFirstLabel(
25-
of: node.argumentList,
25+
of: node.arguments,
2626
with: "fontLiteralName"
2727
)
2828
return ".init(\(argList))"

Tests/MacroTestingTests/MacroExamples/StringifyMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public enum StringifyMacro: ExpressionMacro {
2828
of node: some FreestandingMacroExpansionSyntax,
2929
in context: some MacroExpansionContext
3030
) -> ExprSyntax {
31-
guard let argument = node.argumentList.first?.expression else {
31+
guard let argument = node.arguments.first?.expression else {
3232
fatalError("compiler bug: the macro does not have any arguments")
3333
}
3434

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import SwiftSyntax
2+
import SwiftSyntaxMacros
3+
4+
#if !canImport(SwiftSyntax510) && canImport(SwiftSyntax509)
5+
extension FreestandingMacroExpansionSyntax {
6+
var arguments: LabeledExprListSyntax {
7+
get { self.argumentList }
8+
set { self.argumentList = newValue }
9+
}
10+
}
11+
#endif

Tests/MacroTestingTests/MacroExamples/URLMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public enum URLMacro: ExpressionMacro {
2121
of node: some FreestandingMacroExpansionSyntax,
2222
in context: some MacroExpansionContext
2323
) throws -> ExprSyntax {
24-
guard let argument = node.argumentList.first?.expression,
24+
guard let argument = node.arguments.first?.expression,
2525
let segments = argument.as(StringLiteralExprSyntax.self)?.segments,
2626
segments.count == 1,
2727
case .stringSegment(let literalSegment)? = segments.first

Tests/MacroTestingTests/MacroExamples/WarningMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public enum WarningMacro: ExpressionMacro {
2121
of node: some FreestandingMacroExpansionSyntax,
2222
in context: some MacroExpansionContext
2323
) throws -> ExprSyntax {
24-
guard let firstElement = node.argumentList.first,
24+
guard let firstElement = node.arguments.first,
2525
let stringLiteral = firstElement.expression
2626
.as(StringLiteralExprSyntax.self),
2727
stringLiteral.segments.count == 1,

0 commit comments

Comments
 (0)