10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
+ import SwiftDiagnostics
13
14
import SwiftParser
14
15
import SwiftSyntax
15
16
import SwiftSyntaxBuilder
@@ -132,6 +133,58 @@ struct CheckContextIndependenceMacro: ExpressionMacro {
132
133
}
133
134
}
134
135
136
+ enum CustomError : Error , CustomStringConvertible {
137
+ case message( String )
138
+
139
+ var description : String {
140
+ switch self {
141
+ case . message( let text) :
142
+ return text
143
+ }
144
+ }
145
+ }
146
+
147
+ struct SimpleDiagnosticMessage : DiagnosticMessage {
148
+ let message : String
149
+ let diagnosticID : MessageID
150
+ let severity : DiagnosticSeverity
151
+ }
152
+
153
+ extension SimpleDiagnosticMessage : FixItMessage {
154
+ var fixItID : MessageID { diagnosticID }
155
+ }
156
+
157
+ public struct ErrorMacro : ExpressionMacro {
158
+ public static func expansion(
159
+ of macro: MacroExpansionExprSyntax ,
160
+ in context: inout MacroExpansionContext
161
+ ) throws -> ExprSyntax {
162
+ guard let firstElement = macro. argumentList. first,
163
+ let stringLiteral = firstElement. expression
164
+ . as ( StringLiteralExprSyntax . self) ,
165
+ stringLiteral. segments. count == 1 ,
166
+ case let . stringSegment( messageString) = stringLiteral. segments [ 0 ]
167
+ else {
168
+ throw CustomError . message ( " #error macro requires a string literal " )
169
+ }
170
+
171
+ context. diagnose (
172
+ Diagnostic (
173
+ node: Syntax ( macro) ,
174
+ message: SimpleDiagnosticMessage (
175
+ message: messageString. content. description,
176
+ diagnosticID: MessageID ( domain: " test " , id: " error " ) ,
177
+ severity: . error
178
+ )
179
+ )
180
+ )
181
+
182
+ return " () "
183
+ }
184
+ }
185
+
186
+ // MARK: Assertion helper functions
187
+
135
188
/// Assert that expanding the given macros in the original source produces
136
189
/// the given expanded source code.
137
190
///
@@ -146,11 +199,12 @@ struct CheckContextIndependenceMacro: ExpressionMacro {
146
199
/// - expandedSource: The source code that we expect to see after performing
147
200
/// macro expansion on the original source.
148
201
public func AssertMacroExpansion(
149
- macros: [ String : Macro . Type ] ,
202
+ macros: [ String : Macro . Type ] ,
150
203
testModuleName: String = " TestModule " ,
151
204
testFileName: String = " test.swift " ,
152
205
_ originalSource: String ,
153
206
_ expandedSource: String ,
207
+ diagnosticStrings: [ String ] = [ ] ,
154
208
file: StaticString = #file,
155
209
line: UInt = #line
156
210
) {
@@ -170,15 +224,25 @@ public func AssertMacroExpansion(
170
224
file: file,
171
225
line: line
172
226
)
227
+
228
+ let diags = context. diagnostics
229
+ XCTAssertEqual ( diags. count, diagnosticStrings. count)
230
+ for (actualDiag, expectedDiag) in zip ( diags, diagnosticStrings) {
231
+ let actualMessage = actualDiag. message
232
+ XCTAssertEqual ( actualMessage, expectedDiag)
233
+ }
173
234
}
174
235
236
+ // MARK: Tests
237
+
175
238
/// The set of test macros we use here.
176
- public let testMacros : [ String : Macro . Type ] = [
177
- " checkContext " : CheckContextIndependenceMacro . self,
178
- " colorLiteral " : ColorLiteralMacro . self,
179
- " fileID " : FileIDMacro . self,
180
- " imageLiteral " : ImageLiteralMacro . self,
181
- " stringify " : StringifyMacro . self,
239
+ public let testMacros : [ String : Macro . Type ] = [
240
+ " checkContext " : CheckContextIndependenceMacro . self,
241
+ " colorLiteral " : ColorLiteralMacro . self,
242
+ " fileID " : FileIDMacro . self,
243
+ " imageLiteral " : ImageLiteralMacro . self,
244
+ " stringify " : StringifyMacro . self,
245
+ " myError " : ErrorMacro . self,
182
246
]
183
247
184
248
final class MacroSystemTests : XCTestCase {
@@ -198,7 +262,7 @@ final class MacroSystemTests: XCTestCase {
198
262
199
263
func testStringifyExpression( ) {
200
264
AssertMacroExpansion (
201
- macros: [ " stringify " : StringifyMacro . self] ,
265
+ macros: [ " stringify " : StringifyMacro . self] ,
202
266
"""
203
267
_ = #stringify({ () -> Bool in
204
268
print( " hello " )
@@ -242,7 +306,7 @@ final class MacroSystemTests: XCTestCase {
242
306
243
307
func testContextIndependence( ) {
244
308
AssertMacroExpansion (
245
- macros: [ " checkContext " : CheckContextIndependenceMacro . self] ,
309
+ macros: [ " checkContext " : CheckContextIndependenceMacro . self] ,
246
310
"""
247
311
let b = #checkContext
248
312
""" ,
@@ -251,4 +315,23 @@ final class MacroSystemTests: XCTestCase {
251
315
"""
252
316
)
253
317
}
318
+
319
+ func testErrorExpansion( ) {
320
+ AssertMacroExpansion (
321
+ macros: testMacros,
322
+ """
323
+ _ = #myError( " please don't do that " )
324
+ _ = #myError(bad)
325
+ """ ,
326
+ """
327
+ _ = ()
328
+ _ = #myError(bad)
329
+ """ ,
330
+ diagnosticStrings: [
331
+ " please don't do that " ,
332
+ " #error macro requires a string literal " ,
333
+ ]
334
+ )
335
+ }
336
+
254
337
}
0 commit comments