Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add swift-syntax 510 support; matrix testing for swift-syntax versions #34

Merged
merged 1 commit into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ jobs:
macos:
name: macOS
runs-on: macos-13
strategy:
matrix:
swift-syntax-version: ['509.0.0..<510.0.0', '510.0.0..<511.0.0']

steps:
- uses: actions/checkout@v4
- name: Select Xcode 15
run: sudo xcode-select -s /Applications/Xcode_15.0.app
- name: Set SWIFT_SYNTAX_VERSION environment variable
run: echo "SWIFT_SYNTAX_VERSION=${{ matrix.swift-syntax-version }}" >> $GITHUB_ENV
- name: Resolve Dependencies
run: swift package resolve
- name: Run tests
run: swift test

Expand All @@ -29,9 +37,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Install Swift
uses: slashmo/install-swift@v0.4.0
uses: swift-actions/setup-swift@v2
with:
version: 5.9
swift-version: "5.10"
- uses: actions/checkout@v4
- name: Run tests
run: swift test
Expand Down
10 changes: 5 additions & 5 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "59b663f68e69f27a87b45de48cb63264b8194605",
"version" : "1.15.1"
"revision" : "625ccca8570773dd84a34ee51a81aa2bc5a4f97a",
"version" : "1.16.0"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036",
"version" : "509.0.2"
"revision" : "fa8f95c2d536d6620cc2f504ebe8a6167c9fc2dd",
"version" : "510.0.1"
}
}
],
Expand Down
61 changes: 60 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// swift-tools-version: 5.9

import CompilerPluginSupport
import Foundation
import PackageDescription

let package = Package(
Expand All @@ -23,7 +24,13 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.15.0"),
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0"),
//.conditionalPackage(url: "https://github.com/apple/swift-syntax", envVar: "SWIFT_SYNTAX_VERSION", default: "509.0.0..<510.0.0")
//.conditionalPackage(url: "https://github.com/apple/swift-syntax", envVar: "SWIFT_SYNTAX_VERSION", default: "510.0.0..<511.0.0")
.conditionalPackage(
url: "https://github.com/apple/swift-syntax",
envVar: "SWIFT_SYNTAX_VERSION",
default: "509.0.0..<511.0.0"
),
],
targets: [
.macro(
Expand Down Expand Up @@ -68,3 +75,55 @@ let package = Package(
),
]
)

extension Package.Dependency {
/// Creates a dependency based on an environment variable or a default version range.
///
/// This function allows dynamically setting the version range of a package dependency via an environment variable.
/// If the environment variable is not set, it falls back to a specified default version range.
///
/// - Parameters:
/// - url: The URL of the package repository.
/// - envVar: The name of the environment variable that contains the version range.
/// - versionExpression: The default version range in case the environment variable is not set.
/// Example format: `"509.0.0..<511.0.0"` or `"509.0.0...510.0.0"`.
/// - Returns: A `Package.Dependency` configured with the specified or default version range.
/// - Throws: A fatal error if the version expression format is invalid or the range operator is unsupported.
///
static func conditionalPackage(
url: String,
envVar: String,
default versionExpression: String
) -> Package.Dependency {
let versionRangeString = ProcessInfo.processInfo.environment[envVar] ?? versionExpression
let (lower, op, upper) = parseVersionExpression(from: versionRangeString)
if op == "..<" {
return .package(url: url, lower..<upper)
} else if op == "..." {
return .package(url: url, lower...upper)
} else {
fatalError("Unsupported version range operator: \(op)")
}
}

private static func parseVersionExpression(
from expression: String
) -> (Version, String, Version) {
let rangeOperators = ["..<", "..."]
for op in rangeOperators {
if expression.contains(op) {
let parts = expression.split(separator: op, maxSplits: 1, omittingEmptySubsequences: true)
.map(String.init)
guard
parts.count == 2,
let lower = Version(parts[0]),
let upper = Version(parts[1])
else {
fatalError("Invalid version expression format: \(expression)")
}
return (lower, op, upper)
}
}
fatalError("No valid range operator found in expression: \(expression)")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ extension ExprSyntax {
else { return nil }
return .tuple(elementTypes)

#if canImport(SwiftSyntax510)
case .thenStmt:
return nil
#endif

case .token, .accessorBlock, .accessorDeclList, .accessorDecl, .accessorEffectSpecifiers,
.accessorParameters, .actorDecl, .arrayElementList, .arrayElement, .arrayType, .arrowExpr,
.assignmentExpr, .associatedTypeDecl, .attributeList, .attribute, .attributedType,
Expand Down
85 changes: 60 additions & 25 deletions Tests/MacroTestingTests/DictionaryStorageMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,73 @@ final class DictionaryStorageMacroTests: BaseTestCase {
}

func testExpansionConvertsStoredProperties() {
assertMacro {
"""
@DictionaryStorage
struct Point {
var x: Int = 1
var y: Int = 2
}
"""
} expansion: {
"""
struct Point {
var x: Int = 1 {
get {
_storage["x", default: 1] as! Int
#if canImport(SwiftSyntax510)
assertMacro {
"""
@DictionaryStorage
struct Point {
var x: Int = 1
var y: Int = 2
}
"""
} expansion: {
"""
struct Point {
var x: Int {
get {
_storage["x", default: 1] as! Int
}
set {
_storage["x"] = newValue
}
}
set {
_storage["x"] = newValue
var y: Int {
get {
_storage["y", default: 2] as! Int
}
set {
_storage["y"] = newValue
}
}

var _storage: [String: Any] = [:]
}
"""
}
#elseif canImport(SwiftSyntax509)
assertMacro {
"""
@DictionaryStorage
struct Point {
var x: Int = 1
var y: Int = 2
}
var y: Int = 2 {
get {
_storage["y", default: 2] as! Int
"""
} expansion: {
"""
struct Point {
var x: Int = 1 {
get {
_storage["x", default: 1] as! Int
}
set {
_storage["x"] = newValue
}
}
set {
_storage["y"] = newValue
var y: Int = 2 {
get {
_storage["y", default: 2] as! Int
}
set {
_storage["y"] = newValue
}
}
}

var _storage: [String: Any] = [:]
var _storage: [String: Any] = [:]
}
"""
}
"""
}
#endif
}

func testExpansionWithoutInitializersEmitsError() {
Expand Down
2 changes: 1 addition & 1 deletion Tests/MacroTestingTests/MacroExamples/AddBlocker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,6 @@ public struct AddBlocker: ExpressionMacro {
context.diagnose(diag)
}

return result.asProtocol(FreestandingMacroExpansionSyntax.self)!.argumentList.first!.expression
return result.asProtocol(FreestandingMacroExpansionSyntax.self)!.arguments.first!.expression
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum FontLiteralMacro: ExpressionMacro {
in context: some MacroExpansionContext
) throws -> ExprSyntax {
let argList = replaceFirstLabel(
of: node.argumentList,
of: node.arguments,
with: "fontLiteralName"
)
return ".init(\(argList))"
Expand Down
2 changes: 1 addition & 1 deletion Tests/MacroTestingTests/MacroExamples/StringifyMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public enum StringifyMacro: ExpressionMacro {
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) -> ExprSyntax {
guard let argument = node.argumentList.first?.expression else {
guard let argument = node.arguments.first?.expression else {
fatalError("compiler bug: the macro does not have any arguments")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import SwiftSyntax
import SwiftSyntaxMacros

#if !canImport(SwiftSyntax510) && canImport(SwiftSyntax509)
extension FreestandingMacroExpansionSyntax {
var arguments: LabeledExprListSyntax {
get { self.argumentList }
set { self.argumentList = newValue }
}
}
#endif
2 changes: 1 addition & 1 deletion Tests/MacroTestingTests/MacroExamples/URLMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public enum URLMacro: ExpressionMacro {
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> ExprSyntax {
guard let argument = node.argumentList.first?.expression,
guard let argument = node.arguments.first?.expression,
let segments = argument.as(StringLiteralExprSyntax.self)?.segments,
segments.count == 1,
case .stringSegment(let literalSegment)? = segments.first
Expand Down
2 changes: 1 addition & 1 deletion Tests/MacroTestingTests/MacroExamples/WarningMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public enum WarningMacro: ExpressionMacro {
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> ExprSyntax {
guard let firstElement = node.argumentList.first,
guard let firstElement = node.arguments.first,
let stringLiteral = firstElement.expression
.as(StringLiteralExprSyntax.self),
stringLiteral.segments.count == 1,
Expand Down
Loading