Skip to content

Commit 46c02e9

Browse files
committed
Don’t add any accessors if accessor macro returned an empty array
If an accessor macro returns an empty array, MacroSystem was failing with internal error messages because it tried ot parse an `AccessorBlockSyntax` from an empty string. To fix this, check if the expanded source is empty before trying to parse the `AccessorBlockSyntax`.
1 parent ddd05ef commit 46c02e9

File tree

8 files changed

+228
-1
lines changed

8 files changed

+228
-1
lines changed

Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ private func expandAccessorMacroWithoutExistingAccessors(
267267
conformanceList: nil,
268268
in: context,
269269
indentationWidth: indentationWidth
270-
)
270+
),
271+
!expanded.isEmpty
271272
else {
272273
return nil
273274
}

Tests/SwiftSyntaxMacroExpansionTest/AccessorMacroTests.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
// macros are invoked. //
1919
//==========================================================================//
2020

21+
import SwiftDiagnostics
2122
import SwiftSyntax
23+
import SwiftSyntaxMacroExpansion
2224
import SwiftSyntaxMacros
2325
import SwiftSyntaxMacrosTestSupport
2426
import XCTest
@@ -261,4 +263,61 @@ final class AccessorMacroTests: XCTestCase {
261263
indentationWidth: indentationWidth
262264
)
263265
}
266+
267+
func testEmpty() {
268+
struct TestMacro: AccessorMacro {
269+
static func expansion(
270+
of node: AttributeSyntax,
271+
providingAccessorsOf declaration: some DeclSyntaxProtocol,
272+
in context: some MacroExpansionContext
273+
) throws -> [AccessorDeclSyntax] {
274+
return []
275+
}
276+
}
277+
278+
// The compiler will reject this with
279+
// 'Expansion of macro 'Test()' did not produce a non-observing accessor'
280+
// We consider this a semantic error because swift-syntax doesn't have
281+
// knowledge about which accessors are observing and which ones aren't.
282+
assertMacroExpansion(
283+
"@Test var x: Int",
284+
expandedSource: "var x: Int",
285+
macros: ["Test": TestMacro.self]
286+
)
287+
288+
assertMacroExpansion(
289+
"@Test var x: Int { 1 }",
290+
expandedSource: "var x: Int { 1 }",
291+
macros: ["Test": TestMacro.self]
292+
)
293+
}
294+
295+
func testEmitErrorFromMacro() {
296+
struct TestMacro: AccessorMacro {
297+
static func expansion(
298+
of node: AttributeSyntax,
299+
providingAccessorsOf declaration: some DeclSyntaxProtocol,
300+
in context: some MacroExpansionContext
301+
) throws -> [AccessorDeclSyntax] {
302+
context.diagnose(Diagnostic(node: node, message: MacroExpansionErrorMessage("test")))
303+
return []
304+
}
305+
}
306+
307+
assertMacroExpansion(
308+
"@Test var x: Int",
309+
expandedSource: "var x: Int",
310+
diagnostics: [
311+
DiagnosticSpec(message: "test", line: 1, column: 1)
312+
],
313+
macros: ["Test": TestMacro.self]
314+
)
315+
316+
assertMacroExpansion(
317+
"@Test var x: Int { 1 }",
318+
expandedSource: "var x: Int { 1 }",
319+
diagnostics: [DiagnosticSpec(message: "test", line: 1, column: 1)],
320+
macros: ["Test": TestMacro.self]
321+
)
322+
}
264323
}

Tests/SwiftSyntaxMacroExpansionTest/CodeItemMacroTests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,23 @@ final class CodeItemMacroTests: XCTestCase {
133133
indentationWidth: indentationWidth
134134
)
135135
}
136+
137+
func testEmpty() {
138+
struct TestMacro: CodeItemMacro {
139+
static func expansion(
140+
of node: some FreestandingMacroExpansionSyntax,
141+
in context: some MacroExpansionContext
142+
) throws -> [CodeBlockItemSyntax] {
143+
return []
144+
}
145+
}
146+
147+
assertMacroExpansion(
148+
"#test",
149+
expandedSource: "",
150+
macros: [
151+
"test": TestMacro.self
152+
]
153+
)
154+
}
136155
}

Tests/SwiftSyntaxMacroExpansionTest/DeclarationMacroTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,4 +389,22 @@ final class DeclarationMacroTests: XCTestCase {
389389
)
390390
}
391391

392+
func testEmpty() {
393+
struct TestMacro: DeclarationMacro {
394+
static func expansion(
395+
of node: some FreestandingMacroExpansionSyntax,
396+
in context: some MacroExpansionContext
397+
) throws -> [DeclSyntax] {
398+
return []
399+
}
400+
}
401+
402+
assertMacroExpansion(
403+
"#test",
404+
expandedSource: "",
405+
macros: [
406+
"test": TestMacro.self
407+
]
408+
)
409+
}
392410
}

Tests/SwiftSyntaxMacroExpansionTest/ExtensionMacroTests.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,26 @@ final class ExtensionMacroTests: XCTestCase {
106106
indentationWidth: indentationWidth
107107
)
108108
}
109+
110+
func testEmpty() {
111+
struct TestMacro: ExtensionMacro {
112+
static func expansion(
113+
of node: AttributeSyntax,
114+
attachedTo declaration: some DeclGroupSyntax,
115+
providingExtensionsOf type: some TypeSyntaxProtocol,
116+
conformingTo protocols: [TypeSyntax],
117+
in context: some MacroExpansionContext
118+
) throws -> [ExtensionDeclSyntax] {
119+
return []
120+
}
121+
}
122+
123+
assertMacroExpansion(
124+
"@Test struct Foo {}",
125+
expandedSource: "struct Foo {}",
126+
macros: [
127+
"Test": TestMacro.self
128+
]
129+
)
130+
}
109131
}

Tests/SwiftSyntaxMacroExpansionTest/MemberAttributeMacroTests.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,48 @@ final class MemberAttributeMacroTests: XCTestCase {
354354
)
355355
}
356356

357+
func testEmpty() {
358+
struct TestMacro: MemberAttributeMacro {
359+
static func expansion(
360+
of node: AttributeSyntax,
361+
attachedTo declaration: some DeclGroupSyntax,
362+
providingAttributesFor member: some DeclSyntaxProtocol,
363+
in context: some MacroExpansionContext
364+
) throws -> [AttributeSyntax] {
365+
return []
366+
}
367+
}
368+
369+
assertMacroExpansion(
370+
"""
371+
@Test
372+
struct Foo {
373+
var x: Int
374+
}
375+
""",
376+
expandedSource: """
377+
struct Foo {
378+
var x: Int
379+
}
380+
""",
381+
macros: [
382+
"Test": TestMacro.self
383+
]
384+
)
385+
386+
assertMacroExpansion(
387+
"""
388+
@Test
389+
struct Foo {
390+
}
391+
""",
392+
expandedSource: """
393+
struct Foo {
394+
}
395+
""",
396+
macros: [
397+
"Test": TestMacro.self
398+
]
399+
)
400+
}
357401
}

Tests/SwiftSyntaxMacroExpansionTest/MemberMacroTests.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,48 @@ final class MemberMacroTests: XCTestCase {
255255
)
256256
}
257257

258+
func testEmpty() {
259+
struct TestMacro: MemberMacro {
260+
static func expansion(
261+
of node: AttributeSyntax,
262+
providingMembersOf declaration: some DeclGroupSyntax,
263+
conformingTo protocols: [TypeSyntax],
264+
in context: some MacroExpansionContext
265+
) throws -> [DeclSyntax] {
266+
return []
267+
}
268+
}
269+
270+
assertMacroExpansion(
271+
"""
272+
@Test
273+
struct Foo {
274+
var x: Int
275+
}
276+
""",
277+
expandedSource: """
278+
struct Foo {
279+
var x: Int
280+
}
281+
""",
282+
macros: [
283+
"Test": TestMacro.self
284+
]
285+
)
286+
287+
assertMacroExpansion(
288+
"""
289+
@Test
290+
struct Foo {
291+
}
292+
""",
293+
expandedSource: """
294+
struct Foo {
295+
}
296+
""",
297+
macros: [
298+
"Test": TestMacro.self
299+
]
300+
)
301+
}
258302
}

Tests/SwiftSyntaxMacroExpansionTest/PeerMacroTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,24 @@ final class PeerMacroTests: XCTestCase {
173173
macros: ["Test": TestMacro.self]
174174
)
175175
}
176+
177+
func testEmpty() {
178+
struct TestMacro: PeerMacro {
179+
static func expansion(
180+
of node: AttributeSyntax,
181+
providingPeersOf declaration: some DeclSyntaxProtocol,
182+
in context: some MacroExpansionContext
183+
) throws -> [DeclSyntax] {
184+
return []
185+
}
186+
}
187+
188+
assertMacroExpansion(
189+
"@Test var x: Int",
190+
expandedSource: "var x: Int",
191+
macros: [
192+
"Test": TestMacro.self
193+
]
194+
)
195+
}
176196
}

0 commit comments

Comments
 (0)