Skip to content

Commit 728a6c3

Browse files
committed
Add samples and update CI
1 parent 0f1f50b commit 728a6c3

File tree

13 files changed

+201
-1
lines changed

13 files changed

+201
-1
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ jobs:
2929
with:
3030
api-level: 28
3131
arch: x86_64
32-
script: runall.sh
32+
script: ./runall.sh
3333

macro-sample/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

macro-sample/Package.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// swift-tools-version: 6.1
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
import CompilerPluginSupport
6+
7+
let package = Package(
8+
name: "MacrosDemo",
9+
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
10+
products: [
11+
// Products define the executables and libraries a package produces, making them visible to other packages.
12+
.library(
13+
name: "MacrosDemo",
14+
targets: ["MacrosDemo"]
15+
),
16+
.executable(
17+
name: "MacrosDemoClient",
18+
targets: ["MacrosDemoClient"]
19+
),
20+
],
21+
dependencies: [
22+
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "600.0.0-latest"),
23+
],
24+
targets: [
25+
// Targets are the basic building blocks of a package, defining a module or a test suite.
26+
// Targets can depend on other targets in this package and products from dependencies.
27+
// Macro implementation that performs the source transformation of a macro.
28+
.macro(
29+
name: "MacrosDemoMacros",
30+
dependencies: [
31+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
32+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
33+
]
34+
),
35+
36+
// Library that exposes a macro as part of its API, which is used in client programs.
37+
.target(name: "MacrosDemo", dependencies: ["MacrosDemoMacros"]),
38+
39+
// A client of the library, which is able to use the macro in its own code.
40+
.executableTarget(name: "MacrosDemoClient", dependencies: ["MacrosDemo"]),
41+
42+
// A test target used to develop the macro implementation.
43+
.testTarget(
44+
name: "MacrosDemoTests",
45+
dependencies: [
46+
"MacrosDemoMacros",
47+
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
48+
]
49+
),
50+
]
51+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// The Swift Programming Language
2+
// https://docs.swift.org/swift-book
3+
4+
/// A macro that produces both a value and a string containing the
5+
/// source code that generated the value. For example,
6+
///
7+
/// #stringify(x + y)
8+
///
9+
/// produces a tuple `(x + y, "x + y")`.
10+
@freestanding(expression)
11+
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacrosDemoMacros", type: "StringifyMacro")
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import MacrosDemo
2+
3+
let a = 17
4+
let b = 25
5+
6+
let (result, code) = #stringify(a + b)
7+
8+
print("The value \(result) was produced by the code \"\(code)\"")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import SwiftCompilerPlugin
2+
import SwiftSyntax
3+
import SwiftSyntaxBuilder
4+
import SwiftSyntaxMacros
5+
6+
/// Implementation of the `stringify` macro, which takes an expression
7+
/// of any type and produces a tuple containing the value of that expression
8+
/// and the source code that produced the value. For example
9+
///
10+
/// #stringify(x + y)
11+
///
12+
/// will expand to
13+
///
14+
/// (x + y, "x + y")
15+
public struct StringifyMacro: ExpressionMacro {
16+
public static func expansion(
17+
of node: some FreestandingMacroExpansionSyntax,
18+
in context: some MacroExpansionContext
19+
) -> ExprSyntax {
20+
guard let argument = node.arguments.first?.expression else {
21+
fatalError("compiler bug: the macro does not have any arguments")
22+
}
23+
24+
return "(\(argument), \(literal: argument.description))"
25+
}
26+
}
27+
28+
@main
29+
struct MacrosDemoPlugin: CompilerPlugin {
30+
let providingMacros: [Macro.Type] = [
31+
StringifyMacro.self,
32+
]
33+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import SwiftSyntax
2+
import SwiftSyntaxBuilder
3+
import SwiftSyntaxMacros
4+
import SwiftSyntaxMacrosTestSupport
5+
import XCTest
6+
7+
// Macro implementations build for the host, so the corresponding module is not available when cross-compiling. Cross-compiled tests may still make use of the macro itself in end-to-end tests.
8+
#if canImport(MacrosDemoMacros)
9+
import MacrosDemoMacros
10+
11+
let testMacros: [String: Macro.Type] = [
12+
"stringify": StringifyMacro.self,
13+
]
14+
#endif
15+
16+
final class MacrosDemoTests: XCTestCase {
17+
func testMacro() throws {
18+
#if canImport(MacrosDemoMacros)
19+
assertMacroExpansion(
20+
"""
21+
#stringify(a + b)
22+
""",
23+
expandedSource: """
24+
(a + b, "a + b")
25+
""",
26+
macros: testMacros
27+
)
28+
#else
29+
throw XCTSkip("macros are only supported when running tests for the host platform")
30+
#endif
31+
}
32+
33+
func testMacroWithStringLiteral() throws {
34+
#if canImport(MacrosDemoMacros)
35+
assertMacroExpansion(
36+
#"""
37+
#stringify("Hello, \(name)")
38+
"""#,
39+
expandedSource: #"""
40+
("Hello, \(name)", #""Hello, \(name)""#)
41+
"""#,
42+
macros: testMacros
43+
)
44+
#else
45+
throw XCTSkip("macros are only supported when running tests for the host platform")
46+
#endif
47+
}
48+
}

macro-sample/run.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh -ex
2+
skip android test

testing-sample/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

testing-sample/Package.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// swift-tools-version: 6.1
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "LibraryDemo",
6+
products: [
7+
.library(
8+
name: "LibraryDemo",
9+
targets: ["LibraryDemo"]
10+
),
11+
],
12+
targets: [
13+
.target(
14+
name: "LibraryDemo"
15+
),
16+
.testTarget(
17+
name: "LibraryDemoTests",
18+
dependencies: ["LibraryDemo"]
19+
),
20+
]
21+
)

0 commit comments

Comments
 (0)