Skip to content

Commit 3914c0b

Browse files
De-duplicated diagnostic (#2353)
1 parent 806121d commit 3914c0b

File tree

2 files changed

+19
-31
lines changed

2 files changed

+19
-31
lines changed

Examples/Sources/MacroExamples/Implementation/ComplexMacros/OptionSetMacro.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public struct OptionSetMacro {
7979
static func decodeExpansion(
8080
of attribute: AttributeSyntax,
8181
attachedTo decl: some DeclGroupSyntax,
82-
in context: some MacroExpansionContext
82+
in context: some MacroExpansionContext,
83+
emitDiagnostics: Bool
8384
) -> (StructDeclSyntax, EnumDeclSyntax, TypeSyntax)? {
8485
// Determine the name of the options enum.
8586
let optionsEnumName: String
@@ -91,7 +92,9 @@ public struct OptionSetMacro {
9192
stringLiteral.segments.count == 1,
9293
case let .stringSegment(optionsEnumNameString)? = stringLiteral.segments.first
9394
else {
94-
context.diagnose(OptionSetMacroDiagnostic.requiresStringLiteral(optionsEnumNameArgumentLabel).diagnose(at: optionEnumNameArg.expression))
95+
if emitDiagnostics {
96+
context.diagnose(OptionSetMacroDiagnostic.requiresStringLiteral(optionsEnumNameArgumentLabel).diagnose(at: optionEnumNameArg.expression))
97+
}
9598
return nil
9699
}
97100

@@ -102,7 +105,9 @@ public struct OptionSetMacro {
102105

103106
// Only apply to structs.
104107
guard let structDecl = decl.as(StructDeclSyntax.self) else {
105-
context.diagnose(OptionSetMacroDiagnostic.requiresStruct.diagnose(at: decl))
108+
if emitDiagnostics {
109+
context.diagnose(OptionSetMacroDiagnostic.requiresStruct.diagnose(at: decl))
110+
}
106111
return nil
107112
}
108113

@@ -118,15 +123,19 @@ public struct OptionSetMacro {
118123
return nil
119124
}).first
120125
else {
121-
context.diagnose(OptionSetMacroDiagnostic.requiresOptionsEnum(optionsEnumName).diagnose(at: decl))
126+
if emitDiagnostics {
127+
context.diagnose(OptionSetMacroDiagnostic.requiresOptionsEnum(optionsEnumName).diagnose(at: decl))
128+
}
122129
return nil
123130
}
124131

125132
// Retrieve the raw type from the attribute.
126133
guard let genericArgs = attribute.attributeName.as(IdentifierTypeSyntax.self)?.genericArgumentClause,
127134
let rawType = genericArgs.arguments.first?.argument
128135
else {
129-
context.diagnose(OptionSetMacroDiagnostic.requiresOptionsEnumRawType.diagnose(at: attribute))
136+
if emitDiagnostics {
137+
context.diagnose(OptionSetMacroDiagnostic.requiresOptionsEnumRawType.diagnose(at: attribute))
138+
}
130139
return nil
131140
}
132141

@@ -143,7 +152,7 @@ extension OptionSetMacro: ExtensionMacro {
143152
in context: some MacroExpansionContext
144153
) throws -> [ExtensionDeclSyntax] {
145154
// Decode the expansion arguments.
146-
guard let (structDecl, _, _) = decodeExpansion(of: node, attachedTo: declaration, in: context) else {
155+
guard let (structDecl, _, _) = decodeExpansion(of: node, attachedTo: declaration, in: context, emitDiagnostics: false) else {
147156
return []
148157
}
149158

@@ -165,7 +174,7 @@ extension OptionSetMacro: MemberMacro {
165174
in context: some MacroExpansionContext
166175
) throws -> [DeclSyntax] {
167176
// Decode the expansion arguments.
168-
guard let (_, optionsEnum, rawType) = decodeExpansion(of: attribute, attachedTo: decl, in: context) else {
177+
guard let (_, optionsEnum, rawType) = decodeExpansion(of: attribute, attachedTo: decl, in: context, emitDiagnostics: true) else {
169178
return []
170179
}
171180

Examples/Tests/MacroExamples/Implementation/ComplexMacros/OptionSetMacroTests.swift

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,7 @@ final class OptionSetMacroTests: XCTestCase {
139139
message: "'OptionSet' macro can only be applied to a struct",
140140
line: 1,
141141
column: 1
142-
),
143-
/// The diagnostic is duplicated because it's generated first by `ExtensionMacro` and then by `MemberMacro`.
144-
/// Consider refactoring this in the future.
145-
DiagnosticSpec(
146-
message: "'OptionSet' macro can only be applied to a struct",
147-
line: 1,
148-
column: 1
149-
),
142+
)
150143
],
151144
macros: macros,
152145
indentationWidth: .spaces(2)
@@ -173,14 +166,7 @@ final class OptionSetMacroTests: XCTestCase {
173166
message: "'OptionSet' macro requires nested options enum 'Options'",
174167
line: 1,
175168
column: 1
176-
),
177-
/// The diagnostic is duplicated because it's generated first by `ExtensionMacro` and then by `MemberMacro`.
178-
/// Consider refactoring this in the future.
179-
DiagnosticSpec(
180-
message: "'OptionSet' macro requires nested options enum 'Options'",
181-
line: 1,
182-
column: 1
183-
),
169+
)
184170
],
185171
macros: macros,
186172
indentationWidth: .spaces(2)
@@ -209,14 +195,7 @@ final class OptionSetMacroTests: XCTestCase {
209195
message: "'OptionSet' macro requires a raw type",
210196
line: 1,
211197
column: 1
212-
),
213-
/// The diagnostic is duplicated because it's generated first by `ExtensionMacro` and then by `MemberMacro`.
214-
/// Consider refactoring this in the future.
215-
DiagnosticSpec(
216-
message: "'OptionSet' macro requires a raw type",
217-
line: 1,
218-
column: 1
219-
),
198+
)
220199
],
221200
macros: macros,
222201
indentationWidth: .spaces(2)

0 commit comments

Comments
 (0)