|
9 | 9 | // |
10 | 10 |
|
11 | 11 | import SwiftDiagnostics |
| 12 | +import SwiftIfConfig |
12 | 13 | import SwiftParser |
13 | 14 | import SwiftSyntax |
14 | 15 | import SwiftSyntaxBuilder |
@@ -94,8 +95,19 @@ struct DiagnosticMessage: SwiftDiagnostics.DiagnosticMessage { |
94 | 95 | /// - Returns: The name of the macro as understood by a developer, such as |
95 | 96 | /// `"'@Test'"`. Include single quotes. |
96 | 97 | private static func _macroName(_ attribute: AttributeSyntax) -> String { |
| 98 | + var attributeName = attribute.attributeName |
| 99 | + if let type = attributeName.as(IdentifierTypeSyntax.self) { |
| 100 | + attributeName = TypeSyntax(type.with(\.genericArgumentClause, nil)) |
| 101 | + } else if let type = attributeName.as(MemberTypeSyntax.self) { |
| 102 | + attributeName = TypeSyntax(type.with(\.genericArgumentClause, nil)) |
| 103 | + } |
| 104 | + let attributeNameText = attributeName |
| 105 | + .tokens(viewMode: .fixedUp) |
| 106 | + .map(\.textWithoutBackticks) |
| 107 | + .joined() |
| 108 | + |
97 | 109 | // SEE: https://github.com/swiftlang/swift/blob/main/docs/Diagnostics.md?plain=1#L44 |
98 | | - "'\(attribute.attributeNameText)'" |
| 110 | + return "'\(attributeNameText)'" |
99 | 111 | } |
100 | 112 |
|
101 | 113 | /// Get a string corresponding to the specified syntax node (for instance, |
@@ -197,6 +209,39 @@ struct DiagnosticMessage: SwiftDiagnostics.DiagnosticMessage { |
197 | 209 | } |
198 | 210 | } |
199 | 211 |
|
| 212 | + /// Create a diagnostic message stating that the given attribute has an unused |
| 213 | + /// generic argument clause (e.g. `@Test<T>`). |
| 214 | + /// |
| 215 | + /// - Parameters: |
| 216 | + /// - attribute: The `@Test` or `@Suite` attribute. |
| 217 | + /// - decl: The generic declaration in question. |
| 218 | + /// - genericClause: The child node on `attribute` that makes it generic. |
| 219 | + /// |
| 220 | + /// - Returns: A diagnostic message. |
| 221 | + static func genericAttributeNotSupported(_ attribute: AttributeSyntax, on decl: some SyntaxProtocol, becauseOf genericClause: some SyntaxProtocol, languageMode: VersionTuple?) -> Self { |
| 222 | + let fixIts: [FixIt] = [ |
| 223 | + FixIt( |
| 224 | + message: MacroExpansionFixItMessage("Remove generic attribute clause from \(_macroName(attribute))"), |
| 225 | + changes: [.replace(oldNode: Syntax(genericClause), newNode: Syntax("" as ExprSyntax))] |
| 226 | + ), |
| 227 | + ] |
| 228 | + if let languageMode, languageMode >= .init(7, 0) { |
| 229 | + return Self( |
| 230 | + syntax: Syntax(genericClause), |
| 231 | + message: "Generic argument clause of attribute \(_macroName(attribute)) is unsupported", |
| 232 | + severity: .error, |
| 233 | + fixIts: fixIts |
| 234 | + ) |
| 235 | + } else { |
| 236 | + return Self( |
| 237 | + syntax: Syntax(genericClause), |
| 238 | + message: "Generic argument clause of attribute \(_macroName(attribute)) is unsupported; this is an error in the Swift 7 language mode", |
| 239 | + severity: .warning, |
| 240 | + fixIts: fixIts |
| 241 | + ) |
| 242 | + } |
| 243 | + } |
| 244 | + |
200 | 245 | /// Create a diagnostic message stating that the `@Test` or `@Suite` attribute |
201 | 246 | /// cannot be applied to a type that also has an availability attribute. |
202 | 247 | /// |
|
0 commit comments