-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e8f0299
commit 3883fea
Showing
92 changed files
with
6,670 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
8 changes: 8 additions & 0 deletions
8
.../Experimentation/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// swift-tools-version: 5.9 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
import CompilerPluginSupport | ||
|
||
let package = Package( | ||
name: "Experimentation", | ||
platforms: [.macOS(.v10_15), .iOS(.v17), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)], | ||
products: [ | ||
// Products define the executables and libraries a package produces, making them visible to other packages. | ||
.library( | ||
name: "Experimentation", | ||
targets: ["Experimentation"] | ||
), | ||
.executable( | ||
name: "ExperimentationClient", | ||
targets: ["ExperimentationClient"] | ||
), | ||
], | ||
dependencies: [ | ||
// Depend on the latest Swift 5.9 prerelease of SwiftSyntax | ||
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b"), | ||
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.1.0") | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
// Macro implementation that performs the source transformation of a macro. | ||
.macro( | ||
name: "ExperimentationMacros", | ||
dependencies: [ | ||
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"), | ||
.product(name: "SwiftCompilerPlugin", package: "swift-syntax") | ||
] | ||
), | ||
|
||
// Library that exposes a macro as part of its API, which is used in client programs. | ||
.target(name: "Experimentation", dependencies: ["ExperimentationMacros"]), | ||
|
||
// A client of the library, which is able to use the macro in its own code. | ||
.executableTarget(name: "ExperimentationClient", dependencies: ["Experimentation"]), | ||
|
||
// A test target used to develop the macro implementation. | ||
.testTarget( | ||
name: "ExperimentationTests", | ||
dependencies: [ | ||
"ExperimentationMacros", | ||
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), | ||
.product(name: "MacroTesting", package: "swift-macro-testing") | ||
] | ||
), | ||
] | ||
) |
11 changes: 11 additions & 0 deletions
11
0250-macro-testing-pt1/Experimentation/Sources/Experimentation/Experimentation.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// The Swift Programming Language | ||
// https://docs.swift.org/swift-book | ||
|
||
/// A macro that produces both a value and a string containing the | ||
/// source code that generated the value. For example, | ||
/// | ||
/// #stringify(x + y) | ||
/// | ||
/// produces a tuple `(x + y, "x + y")`. | ||
@freestanding(expression) | ||
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "ExperimentationMacros", type: "StringifyMacro") |
10 changes: 10 additions & 0 deletions
10
0250-macro-testing-pt1/Experimentation/Sources/ExperimentationClient/main.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Experimentation | ||
|
||
let a = 17 | ||
let b = 25 | ||
|
||
let (result, code) = #stringify(a + b) | ||
|
||
//let (result1, code1) = #stringify() | ||
|
||
print("The value \(result) was produced by the code \"\(code)\"") |
40 changes: 40 additions & 0 deletions
40
...acro-testing-pt1/Experimentation/Sources/ExperimentationMacros/ExperimentationMacro.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import SwiftCompilerPlugin | ||
import SwiftSyntax | ||
import SwiftSyntaxBuilder | ||
import SwiftSyntaxMacros | ||
|
||
/// Implementation of the `stringify` macro, which takes an expression | ||
/// of any type and produces a tuple containing the value of that expression | ||
/// and the source code that produced the value. For example | ||
/// | ||
/// #stringify(x + y) | ||
/// | ||
/// will expand to | ||
/// | ||
/// (x + y, "x + y") | ||
public struct StringifyMacro: ExpressionMacro { | ||
public static func expansion<F: FreestandingMacroExpansionSyntax, C: MacroExpansionContext>( | ||
of node: F, | ||
in context: C | ||
) throws -> ExprSyntax { | ||
guard let argument = node.argumentList.first?.expression else { | ||
fatalError("compiler bug: the macro does not have any arguments") | ||
} | ||
|
||
guard argument.description.count < 20 | ||
else { | ||
throw SomeError() | ||
} | ||
|
||
return "(\(argument), \(literal: argument.description))" | ||
} | ||
} | ||
|
||
struct SomeError: Error {} | ||
|
||
@main | ||
struct ExperimentationPlugin: CompilerPlugin { | ||
let providingMacros: [Macro.Type] = [ | ||
StringifyMacro.self, | ||
] | ||
} |
119 changes: 119 additions & 0 deletions
119
0250-macro-testing-pt1/Experimentation/Tests/ExperimentationTests/ExperimentationTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import MacroTesting | ||
import InlineSnapshotTesting | ||
import SwiftSyntaxMacros | ||
import SwiftSyntaxMacrosTestSupport | ||
import SwiftUI | ||
import XCTest | ||
|
||
// 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. | ||
#if canImport(ExperimentationMacros) | ||
import ExperimentationMacros | ||
|
||
let testMacros: [String: Macro.Type] = [ | ||
"stringify": StringifyMacro.self, | ||
] | ||
#endif | ||
|
||
final class ExperimentationTests: XCTestCase { | ||
override func invokeTest() { | ||
withMacroTesting( | ||
// isRecording: true, | ||
macros: [StringifyMacro.self] | ||
) { | ||
super.invokeTest() | ||
} | ||
} | ||
|
||
func testMacro() throws { | ||
#if canImport(ExperimentationMacros) | ||
assertMacroExpansion( | ||
""" | ||
#stringify(a + b) | ||
""", | ||
expandedSource: """ | ||
(a + b, "a + b") | ||
""", | ||
macros: testMacros | ||
) | ||
#else | ||
throw XCTSkip("macros are only supported when running tests for the host platform") | ||
#endif | ||
} | ||
|
||
func testMacro_Improved() { | ||
assertMacro { | ||
"#stringify(a + b)" | ||
} matches: { | ||
""" | ||
(a + b, "a + b") | ||
""" | ||
} | ||
SnapshotTesting.diffTool = "ksdiff" | ||
assertSnapshot( | ||
of: Text("Bye") | ||
.frame(width: 200, height: 200) | ||
.background { | ||
Color.yellow.opacity(0.2) | ||
}, | ||
as: .image | ||
) | ||
struct User: Codable { | ||
let id: Int | ||
var name: String | ||
} | ||
assertInlineSnapshot(of: User(id: 42, name: "Blob"), as: .json) { | ||
""" | ||
{ | ||
"id" : 42, | ||
"name" : "Blob" | ||
} | ||
""" | ||
} | ||
} | ||
|
||
func testMacro_LongArgumentDiagnostic() throws { | ||
assertMacroExpansion( | ||
""" | ||
#stringify((a + b) * (a - b) * (b - a)) | ||
""", | ||
expandedSource: """ | ||
#stringify((a + b) * (a - b) * (b - a)) | ||
""", | ||
diagnostics: [ | ||
DiagnosticSpec(message: "SomeError()", line: 1, column: 1), | ||
DiagnosticSpec(message: "SomeError()", line: 1, column: 1), | ||
], | ||
macros: testMacros | ||
) | ||
} | ||
|
||
func testMacro_LongArgumentDiagnostic_Improved() throws { | ||
assertMacro { | ||
""" | ||
let (result, string) = #stringify((a + b) * (a - b) * (b - a)) | ||
""" | ||
} matches: { | ||
""" | ||
let (result, string) = #stringify((a + b) * (a - b) * (b - a)) | ||
┬────────────────────────────────────── | ||
╰─ 🛑 SomeError() | ||
""" | ||
} | ||
} | ||
|
||
func testMacroWithStringLiteral() throws { | ||
#if canImport(ExperimentationMacros) | ||
assertMacroExpansion( | ||
#""" | ||
#stringify("Hello, \(name)") | ||
"""#, | ||
expandedSource: #""" | ||
("Hello, \(name)", #""Hello, \(name)""#) | ||
"""#, | ||
macros: testMacros | ||
) | ||
#else | ||
throw XCTSkip("macros are only supported when running tests for the host platform") | ||
#endif | ||
} | ||
} |
Binary file added
BIN
+12.4 KB
...xperimentationTests/__Snapshots__/ExperimentationTests/testMacro_Improved.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions
4
...n/Tests/ExperimentationTests/__Snapshots__/ExperimentationTests/testMacro_Improved.2.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"id" : 42, | ||
"name" : "Blob" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## [Point-Free](https://www.pointfree.co) | ||
|
||
> #### This directory contains code from Point-Free Episode: [Testing & Debugging Macros: Part 1](https://www.pointfree.co/episodes/ep250-testing-debugging-macros-part-1) | ||
> | ||
> Macros are here! To celebrate, we are releasing a brand new tool to aid in writing tests for them. First, let’s explore testing macros using the tools that Apple provides, evaluate their shortcomings, and see how we can address them. |
Oops, something went wrong.