Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 7 additions & 7 deletions Sources/SwiftWarningControl/SwiftWarningControl.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
# SwiftWarningControl

A library to evaluate `@warn` diagnostic group controls within a Swift syntax tree.
A library to evaluate `@diagnose` diagnostic group controls within a Swift syntax tree.

## Overview

Swift provides a mechanism to control the behavior of specific diagnostic groups for a given declaration's lexical scope with the `@warn` attribute.
Swift provides a mechanism to control the behavior of specific diagnostic groups for a given declaration's lexical scope with the `@diagnose` attribute (also accepts the old `@warn` spelling).

The syntax tree and its parser do not reason about warning group controls. The syntax tree produced by the parser represents the `@warn` attribute in a generic fashion, as it would any other basic attribute on a declaration. The per-declaration nature of the attribute means that for any given lexical scope, the behavior of a given diagnostic group can be queried by checking for the presence of this attribute in its parent declaration scope.
The syntax tree and its parser do not reason about warning group controls. The syntax tree produced by the parser represents the `@diagnose` attribute in a generic fashion, as it would any other basic attribute on a declaration. The per-declaration nature of the attribute means that for any given lexical scope, the behavior of a given diagnostic group can be queried by checking for the presence of this attribute in its parent declaration scope.

```swift
@warn(Deprecate, as: error)
@diagnose(Deprecate, as: error)
func foo() {
...
@warn(Deprecate, as: warning)
@diagnose(Deprecate, as: warning)
func bar() {
...
@warn("Deprecate", as: ignored, reason: "Foo")
@diagnose("Deprecate", as: ignored, reason: "Foo")
func baz() {
...
}
}
}
```

The `SwiftWarningControl` library provides a utility to determine, for a given source location and diagnostic group identifier, whether or not its behavior is affected by an `@warn` attribute of any of its parent declaration scope.
The `SwiftWarningControl` library provides a utility to determine, for a given source location and diagnostic group identifier, whether or not its behavior is affected by an `@diagnose` attribute of any of its parent declaration scope.

* `SyntaxProtocol.getWarningGroupControl(for diagnosticGroupIdentifier:)` produces the behavior control specifier (`WarningGroupControl`: `error`, `warning`, `ignored`) which applies at this node.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension SyntaxProtocol {
/// - globalControls: The global controls to consider, specified by the client (compiler)
/// representing module-wide diagnostic group emission configuration, for example
/// with `-Wwarning` and `-Werror` flags. These controls can be overriden at
/// finer-grained scopes with the `@warn` attribute.
/// finer-grained scopes with the `@diagnose` attribute.
@_spi(ExperimentalLanguageFeatures)
public func warningGroupControl(
for diagnosticGroupIdentifier: DiagnosticGroupIdentifier,
Expand Down
7 changes: 4 additions & 3 deletions Sources/SwiftWarningControl/WarningControlDeclSyntax.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

extension AttributeSyntax {
var warningGroupControl: (DiagnosticGroupIdentifier, WarningGroupControl)? {
// `@warn` attributes
guard attributeName.as(IdentifierTypeSyntax.self)?.name.text == "warn"
// `@diagnose` attributes (also accepts the old `@warn` spelling)
guard let attrName = attributeName.as(IdentifierTypeSyntax.self)?.name.text,
attrName == "diagnose" || attrName == "warn"
else {
return nil
}
Expand Down Expand Up @@ -51,7 +52,7 @@ extension AttributeSyntax {
}

extension WithAttributesSyntax {
/// Compute a dictionary of all `@warn` diagnostic group behavior controls
/// Compute a dictionary of all `@diagnose` diagnostic group behavior controls
/// specified on this warning control declaration scope.
var allWarningGroupControls: [(DiagnosticGroupIdentifier, WarningGroupControl)] {
attributes.reduce(into: [(DiagnosticGroupIdentifier, WarningGroupControl)]()) { result, attr in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension SyntaxProtocol {
}
}

/// Add this warning control decl syntax node warning group controls (as specified with `@warn`)
/// Add this warning control decl syntax node warning group controls (as specified with `@diagnose`)
/// to the tree.
extension WarningControlRegionTree {
mutating func addWarningControlRegions(for syntax: some WithAttributesSyntax) {
Expand Down
16 changes: 8 additions & 8 deletions Sources/SwiftWarningControl/WarningControlRegions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,27 @@ public struct DiagnosticGroupIdentifier: Hashable, Sendable, ExpressibleByString
public let identifier: String
}

/// Describes all of the `@warn` diagnostic group behavior controls within the
/// Describes all of the `@diagnose` diagnostic group behavior controls within the
/// given syntax node, indicating each group's active behavior at a given position.
///
/// For example, given code like the following:
///
/// ```
/// 1 | @warn(Deprecate, as: error)
/// 1 | @diagnose(Deprecate, as: error)
/// 2 | func foo() {
/// 3 | let a = dep
/// 4 | @warn(Deprecate, as: warning)
/// 4 | @diagnose(Deprecate, as: warning)
/// 5 | func bar() {
/// 6 | let b = dep
/// 7 | @warn(Deprecate, as: ignored)
/// 7 | @diagnose(Deprecate, as: ignored)
/// 8 | func baz() {
/// 9 | let c = dep
/// 10 | }
/// 11 | @warn(Deprecate, as: error)
/// 12 | @warn(OtherGroup, as: error)
/// 11 | @diagnose(Deprecate, as: error)
/// 12 | @diagnose(OtherGroup, as: error)
/// 13 | func qux() {
/// 14 | let d = dep
/// 15 | @warn(SomeOtherGroup, as: warning)
/// 15 | @diagnose(SomeOtherGroup, as: warning)
/// 16 | func corge() {
/// 17 | let e = dep
/// 18 | }
Expand Down Expand Up @@ -150,7 +150,7 @@ public struct WarningControlRegionTree {
}

/// Add warning control regions to the tree root node.
/// For example, controls corresponding to a top-level `using @warn()` statement.
/// For example, controls corresponding to a top-level `using @diagnose()` statement.
mutating func addRootWarningGroupControls(controls: [(DiagnosticGroupIdentifier, WarningGroupControl)]) {
addWarningGroupControls(range: rootRegionNode.range, controls: controls)
}
Expand Down
33 changes: 33 additions & 0 deletions Tests/SwiftParserTest/DeclarationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3757,6 +3757,39 @@ final class UsingDeclarationTests: ParserTestCase {
)
)

assertParse(
"using @diagnose(DiagGroupID, as: error)",
substructure: UsingDeclSyntax(
usingKeyword: .keyword(.using),
specifier: .attribute(
AttributeSyntax(
attributeName: IdentifierTypeSyntax(
name: .identifier("diagnose")
),
leftParen: .leftParenToken(),
arguments: .argumentList(
LabeledExprListSyntax([
LabeledExprSyntax(
expression: DeclReferenceExprSyntax(
baseName: .identifier("DiagGroupID")
),
trailingComma: .commaToken()
),
LabeledExprSyntax(
label: .identifier("as"),
colon: .colonToken(),
expression: DeclReferenceExprSyntax(
baseName: .identifier("error")
)
),
])
),
rightParen: .rightParenToken()
)
)
)
)

assertParse(
"""
nonisolated
Expand Down
Loading
Loading