Skip to content

Add an attribute that emits a warning. #895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions Sources/Testing/Test+Macro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,24 @@ extension Test {
/// - Note: This macro has compile-time effects _only_ and should not affect a
/// compiled test target.
///
/// - Warning: This macro is used to implement other macros declared by the testing
/// library. Do not use it directly.
/// - Warning: This macro is used to implement other macros declared by the
/// testing library. Do not use it directly.
@attached(peer) public macro __testing(
semantics arguments: _const String...
) = #externalMacro(module: "TestingMacros", type: "PragmaMacro")

/// A macro used similarly to `#warning()` but in a position where only an
/// attribute is valid.
///
/// - Parameters:
/// - message: A string to emit as a warning.
///
/// - Warning: This macro is used to implement other macros declared by the
/// testing library. Do not use it directly.
@attached(peer) public macro __testing(
warning message: _const String
) = #externalMacro(module: "TestingMacros", type: "PragmaMacro")

// MARK: - Helper functions

/// A function that abstracts away whether or not the `try` keyword is needed on
Expand Down
15 changes: 14 additions & 1 deletion Sources/TestingMacros/PragmaMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ public import SwiftSyntaxMacros
///
/// - `@__testing(semantics: "nomacrowarnings")`: suppress warning diagnostics
/// generated by macros. (The implementation of this use case is held in trust
/// at ``MacroExpansionContext/areWarningsSuppressed``.
/// at ``MacroExpansionContext/areWarningsSuppressed``.)
/// - `@__testing(warning: "...")`: emits `"..."` as a diagnostic message
/// attributed to the node to which the attribute is attached.
///
/// This type is used to implement the `@__testing` attribute macro. Do not use
/// it directly.
Expand All @@ -27,6 +29,17 @@ public struct PragmaMacro: PeerMacro, Sendable {
providingPeersOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
if case let .argumentList(arguments) = node.arguments,
arguments.first?.label?.textWithoutBackticks == "warning" {
let targetNode = Syntax(declaration)
let messages = arguments
.map(\.expression)
.compactMap { $0.as(StringLiteralExprSyntax.self) }
.compactMap(\.representedLiteralValue)
.map { DiagnosticMessage(syntax: targetNode, message: $0, severity: .warning) }
context.diagnose(messages)
}

return []
}

Expand Down
18 changes: 15 additions & 3 deletions Tests/TestingMacrosTests/PragmaMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@ import SwiftSyntax
struct PragmaMacroTests {
@Test func findSemantics() throws {
let node = """
@Testing.__testing(semantics: "abc123")
@__testing(semantics: "def456")
let x = 0
@Testing.__testing(semantics: "abc123")
@__testing(semantics: "def456")
let x = 0
""" as DeclSyntax
let nodeWithAttributes = try #require(node.asProtocol((any WithAttributesSyntax).self))
let semantics = semantics(of: nodeWithAttributes)
#expect(semantics == ["abc123", "def456"])
}

@Test func warningGenerated() throws {
let sourceCode = """
@__testing(warning: "abc123")
let x = 0
"""

let (_, diagnostics) = try parse(sourceCode)
#expect(diagnostics.count == 1)
#expect(diagnostics[0].message == "abc123")
#expect(diagnostics[0].diagMessage.severity == .warning)
}
}
1 change: 1 addition & 0 deletions Tests/TestingMacrosTests/TestSupport/Parse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fileprivate let allMacros: [String: any Macro.Type] = [
"Suite": SuiteDeclarationMacro.self,
"Test": TestDeclarationMacro.self,
"Tag": TagMacro.self,
"__testing": PragmaMacro.self,
]

func parse(_ sourceCode: String, activeMacros activeMacroNames: [String] = [], removeWhitespace: Bool = false) throws -> (sourceCode: String, diagnostics: [Diagnostic]) {
Expand Down
2 changes: 2 additions & 0 deletions Tests/TestingTests/MiscellaneousTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,8 @@ struct MiscellaneousTests {
@_section("swift5_tests")
#elseif os(Windows)
@_section(".sw5test$B")
#else
@__testing(warning: "Platform-specific implementation missing: test content section name unavailable")
#endif
@_used
private static let record: __TestContentRecord = (
Expand Down