Skip to content

Commit cfeef41

Browse files
committed
Generalize DeclGroupSyntax casting
Changes `DeclGroupSyntax.requireAs(_:_:)` to be a method on `DeclSyntaxProtocol` instead. This change means we can use more common logic for casting between Syntax types and emitting diagnostics. Introduces some force casts until swiftlang/swift-syntax#2366 makes it into a release.
1 parent 290b28d commit cfeef41

File tree

7 files changed

+178
-85
lines changed

7 files changed

+178
-85
lines changed

Sources/MMIOMacros/Macros/BitFieldMacro.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ extension BitFieldMacro {
3434
in context: MacroContext<Self, some MacroExpansionContext>
3535
) throws -> [AccessorDeclSyntax] {
3636
// Can only applied to variables.
37-
guard let variableDecl = declaration.as(VariableDeclSyntax.self) else {
38-
throw context.error(
39-
at: declaration,
40-
message: .expectedVarDecl())
41-
}
37+
let variableDecl =
38+
try declaration
39+
.requireAs(VariableDeclSyntax.self, context)
4240

4341
// Must be `var` binding.
4442
try variableDecl.require(bindingKind: .var, context)

Sources/MMIOMacros/Macros/RegisterBankMacro.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ extension RegisterBankMacro: MMIOMemberMacro {
3838
in context: MacroContext<Self, some MacroExpansionContext>
3939
) throws -> [DeclSyntax] {
4040
// Can only applied to structs.
41+
// FIXME: https://github.com/apple/swift-syntax/pull/2366
42+
// swift-format-ignore: NeverForceUnwrap
43+
let declaration = declaration as! DeclSyntaxProtocol
4144
let structDecl = try declaration.requireAs(StructDeclSyntax.self, context)
4245

4346
// Walk all the members of the struct.

Sources/MMIOMacros/Macros/RegisterBankOffsetMacro.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ extension RegisterBankOffsetMacro: MMIOAccessorMacro {
4848
in context: MacroContext<Self, some MacroExpansionContext>
4949
) throws -> [AccessorDeclSyntax] {
5050
// Can only applied to variables.
51-
guard let variableDecl = declaration.as(VariableDeclSyntax.self) else {
52-
throw context.error(at: declaration, message: .expectedVarDecl())
53-
}
51+
let variableDecl =
52+
try declaration.requireAs(VariableDeclSyntax.self, context)
5453

5554
// Must be `var` binding.
5655
try variableDecl.require(bindingKind: .var, context)

Sources/MMIOMacros/Macros/RegisterMacro.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ extension RegisterMacro: MMIOMemberMacro {
4646
in context: MacroContext<Self, some MacroExpansionContext>
4747
) throws -> [DeclSyntax] {
4848
// Can only applied to structs.
49+
// FIXME: https://github.com/apple/swift-syntax/pull/2366
50+
// swift-format-ignore: NeverForceUnwrap
51+
let declaration = declaration as! DeclSyntaxProtocol
4952
let structDecl = try declaration.requireAs(StructDeclSyntax.self, context)
5053
let accessLevel = structDecl.accessLevel
5154
let bitWidth = self.bitWidth.value
@@ -150,10 +153,6 @@ extension RegisterMacro: MMIOExtensionMacro {
150153

151154
let `extension`: DeclSyntax = "extension \(type.trimmed): RegisterValue {}"
152155

153-
guard let extensionDecl = `extension`.as(ExtensionDeclSyntax.self) else {
154-
throw context.error(at: `extension`, message: .internalError())
155-
}
156-
157-
return [extensionDecl]
156+
return [try `extension`.requireAs(ExtensionDeclSyntax.self, context)]
158157
}
159158
}

Sources/MMIOMacros/SwiftSyntaxExtensions/DeclGroupSyntax.swift

Lines changed: 0 additions & 59 deletions
This file was deleted.
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
//===----------------------------------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift MMIO open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import SwiftSyntax
13+
import SwiftSyntaxMacros
14+
15+
protocol DiagnosableDeclSyntaxProtocol: DeclSyntaxProtocol {
16+
static var declTypeName: String { get }
17+
var introducerKeyword: TokenSyntax { get }
18+
}
19+
20+
extension AccessorDeclSyntax: DiagnosableDeclSyntaxProtocol {
21+
static var declTypeName = "accessor"
22+
var introducerKeyword: TokenSyntax { self.accessorSpecifier }
23+
}
24+
25+
extension ActorDeclSyntax: DiagnosableDeclSyntaxProtocol {
26+
static let declTypeName = "actor"
27+
var introducerKeyword: TokenSyntax { self.actorKeyword }
28+
}
29+
30+
extension AssociatedTypeDeclSyntax: DiagnosableDeclSyntaxProtocol {
31+
static var declTypeName = "associated type"
32+
var introducerKeyword: TokenSyntax { self.associatedtypeKeyword }
33+
}
34+
35+
extension ClassDeclSyntax: DiagnosableDeclSyntaxProtocol {
36+
static let declTypeName = "class"
37+
var introducerKeyword: TokenSyntax { self.classKeyword }
38+
}
39+
40+
extension DeinitializerDeclSyntax: DiagnosableDeclSyntaxProtocol {
41+
static var declTypeName = "deinitializer"
42+
var introducerKeyword: TokenSyntax { self.deinitKeyword }
43+
}
44+
45+
extension EditorPlaceholderDeclSyntax: DiagnosableDeclSyntaxProtocol {
46+
static var declTypeName = "editor placeholder"
47+
var introducerKeyword: TokenSyntax { self.placeholder }
48+
}
49+
50+
extension EnumCaseDeclSyntax: DiagnosableDeclSyntaxProtocol {
51+
static let declTypeName = "enum case"
52+
var introducerKeyword: TokenSyntax { self.caseKeyword }
53+
}
54+
55+
extension EnumDeclSyntax: DiagnosableDeclSyntaxProtocol {
56+
static let declTypeName = "enum case"
57+
var introducerKeyword: TokenSyntax { self.enumKeyword }
58+
}
59+
60+
extension ExtensionDeclSyntax: DiagnosableDeclSyntaxProtocol {
61+
static let declTypeName = "extension"
62+
var introducerKeyword: TokenSyntax { self.extensionKeyword }
63+
}
64+
65+
extension FunctionDeclSyntax: DiagnosableDeclSyntaxProtocol {
66+
static var declTypeName = "function"
67+
var introducerKeyword: TokenSyntax { self.funcKeyword }
68+
}
69+
70+
extension IfConfigDeclSyntax: DiagnosableDeclSyntaxProtocol {
71+
static var declTypeName = "if config"
72+
var introducerKeyword: TokenSyntax {
73+
self.clauses.first?.poundKeyword ?? .poundToken()
74+
}
75+
}
76+
77+
extension ImportDeclSyntax: DiagnosableDeclSyntaxProtocol {
78+
static var declTypeName = "import"
79+
var introducerKeyword: TokenSyntax { self.importKeyword }
80+
}
81+
82+
extension InitializerDeclSyntax: DiagnosableDeclSyntaxProtocol {
83+
static var declTypeName = "initializer"
84+
var introducerKeyword: TokenSyntax { self.initKeyword }
85+
}
86+
87+
extension MacroDeclSyntax: DiagnosableDeclSyntaxProtocol {
88+
static var declTypeName = "macro"
89+
var introducerKeyword: TokenSyntax { self.macroKeyword }
90+
}
91+
92+
extension MacroExpansionDeclSyntax: DiagnosableDeclSyntaxProtocol {
93+
static var declTypeName = "macro expansion"
94+
var introducerKeyword: TokenSyntax { self.macroName }
95+
}
96+
97+
extension MissingDeclSyntax: DiagnosableDeclSyntaxProtocol {
98+
static var declTypeName = "missing"
99+
var introducerKeyword: TokenSyntax { self.placeholder }
100+
}
101+
102+
extension OperatorDeclSyntax: DiagnosableDeclSyntaxProtocol {
103+
static var declTypeName = "operator"
104+
var introducerKeyword: TokenSyntax { self.operatorKeyword }
105+
}
106+
107+
extension PoundSourceLocationSyntax: DiagnosableDeclSyntaxProtocol {
108+
static var declTypeName = "pound source location"
109+
var introducerKeyword: TokenSyntax { self.poundSourceLocation }
110+
}
111+
112+
extension PrecedenceGroupDeclSyntax: DiagnosableDeclSyntaxProtocol {
113+
static var declTypeName = "precedence group"
114+
var introducerKeyword: TokenSyntax { self.precedencegroupKeyword }
115+
}
116+
117+
extension ProtocolDeclSyntax: DiagnosableDeclSyntaxProtocol {
118+
static let declTypeName = "protocol"
119+
var introducerKeyword: TokenSyntax { self.protocolKeyword }
120+
}
121+
122+
extension StructDeclSyntax: DiagnosableDeclSyntaxProtocol {
123+
static let declTypeName = "struct"
124+
var introducerKeyword: TokenSyntax { self.structKeyword }
125+
}
126+
127+
extension SubscriptDeclSyntax: DiagnosableDeclSyntaxProtocol {
128+
static var declTypeName = "subscript"
129+
var introducerKeyword: TokenSyntax { self.subscriptKeyword }
130+
}
131+
132+
extension TypeAliasDeclSyntax: DiagnosableDeclSyntaxProtocol {
133+
static var declTypeName = "type alias"
134+
var introducerKeyword: TokenSyntax { self.typealiasKeyword }
135+
}
136+
137+
extension VariableDeclSyntax: DiagnosableDeclSyntaxProtocol {
138+
static var declTypeName = "variable"
139+
var introducerKeyword: TokenSyntax { self.bindingSpecifier }
140+
}
141+
142+
extension DeclSyntaxProtocol {
143+
func requireAs<Other>(
144+
_ other: Other.Type,
145+
_ context: MacroContext<some ParsableMacro, some MacroExpansionContext>
146+
) throws -> Other where Other: DiagnosableDeclSyntaxProtocol {
147+
if let decl = self.as(Other.self) { return decl }
148+
149+
let node: any SyntaxProtocol =
150+
(self as? DiagnosableDeclSyntaxProtocol)?.introducerKeyword ?? self
151+
152+
throw context.error(
153+
at: node,
154+
message: .expectedDecl(Other.self))
155+
}
156+
}
157+
158+
extension ErrorDiagnostic {
159+
static func expectedDecl(_ decl: DiagnosableDeclSyntaxProtocol.Type) -> Self {
160+
.init(
161+
"""
162+
'\(Macro.signature)' can only be applied to \(decl.declTypeName) \
163+
declarations
164+
""")
165+
}
166+
}

Sources/MMIOMacros/SwiftSyntaxExtensions/Diagnostics/ErrorDiagnostic.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,6 @@ extension ErrorDiagnostic {
3737
.init("'\(Macro.signature)' internal error. \(Self.internalErrorSuffix)")
3838
}
3939

40-
// Declaration Errors
41-
static func expectedVarDecl() -> Self {
42-
.init("'\(Macro.signature)' can only be applied to properties")
43-
}
44-
45-
static func expectedDecl(_ decl: DiagnosableDeclGroupSyntax.Type) -> Self {
46-
.init(
47-
"""
48-
'\(Macro.signature)' can only be applied to \(decl.declTypeName) \
49-
declarations
50-
""")
51-
}
52-
5340
// Declaration Member Errors
5441
static func onlyMemberVarDecls() -> Self {
5542
.init("'\(Macro.signature)' type can only contain properties")

0 commit comments

Comments
 (0)