Skip to content

Commit bba4f65

Browse files
authored
Merge pull request swiftlang#77404 from rintaro/astgen-diagnostics-simple
[ASTGen] Simplify diagnostics framework
2 parents 4faabc9 + 92c4989 commit bba4f65

File tree

5 files changed

+98
-113
lines changed

5 files changed

+98
-113
lines changed

lib/ASTGen/Sources/ASTGen/ASTGen.swift

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class Boxed<Value> {
6969
}
7070

7171
struct ASTGenVisitor {
72-
fileprivate let diagnosticEngine: BridgedDiagnosticEngine
72+
let diagnosticEngine: BridgedDiagnosticEngine
7373

7474
let base: UnsafeBufferPointer<UInt8>
7575

@@ -280,24 +280,6 @@ extension ASTGenVisitor {
280280
}
281281
}
282282

283-
extension ASTGenVisitor {
284-
/// Emits the given diagnostic via the C++ diagnostic engine.
285-
@inline(__always)
286-
func diagnose(_ diagnostic: Diagnostic) {
287-
emitDiagnostic(
288-
diagnosticEngine: self.diagnosticEngine,
289-
sourceFileBuffer: self.base,
290-
diagnostic: diagnostic,
291-
diagnosticSeverity: diagnostic.diagMessage.severity
292-
)
293-
}
294-
295-
/// Emits the given diagnostics via the C++ diagnostic engine.
296-
func diagnoseAll(_ diagnostics: [Diagnostic]) {
297-
diagnostics.forEach(diagnose)
298-
}
299-
}
300-
301283
// Forwarding overloads that take optional syntax nodes. These are defined on demand to achieve a consistent
302284
// 'self.generate(foo: FooSyntax)' recursion pattern between optional and non-optional inputs.
303285
extension ASTGenVisitor {

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ extension ASTGenVisitor {
340340
case .`init`:
341341
return .`init`
342342
default:
343-
self.diagnose(Diagnostic(node: specifier, message: UnknownAccessorSpecifierError(specifier)))
343+
self.diagnose(.unknownAccessorSpecifier(specifier))
344344
return nil
345345
}
346346
}
@@ -455,7 +455,7 @@ extension ASTGenVisitor {
455455
let storage = primaryVar.asAbstractStorageDecl
456456
storage.setAccessors(generate(accessorBlock: accessors, for: storage))
457457
} else {
458-
self.diagnose(Diagnostic(node: binding.pattern, message: NonTrivialPatternForAccessorError()))
458+
self.diagnose(.nonTrivialPatternForAccessor(binding.pattern))
459459
}
460460
}
461461
return BridgedPatternBindingEntry(
@@ -674,9 +674,7 @@ extension ASTGenVisitor {
674674
fixity = value
675675
} else {
676676
fixity = .infix
677-
self.diagnose(
678-
Diagnostic(node: node.fixitySpecifier, message: UnexpectedTokenKindError(token: node.fixitySpecifier))
679-
)
677+
self.diagnose(.unexpectedTokenKind(token: node.fixitySpecifier))
680678
}
681679

682680
return .createParsed(
@@ -719,9 +717,7 @@ extension ASTGenVisitor {
719717
}
720718

721719
func diagnoseDuplicateSyntax(_ duplicate: some SyntaxProtocol, original: some SyntaxProtocol) {
722-
self.diagnose(
723-
Diagnostic(node: duplicate, message: DuplicateSyntaxError(duplicate: duplicate, original: original))
724-
)
720+
self.diagnose(.duplicateSyntax(duplicate: duplicate, original: original))
725721
}
726722

727723
let body = node.groupAttributes.reduce(into: PrecedenceGroupBody()) { body, element in
@@ -742,7 +738,7 @@ extension ASTGenVisitor {
742738
body.lowerThanRelation = relation
743739
}
744740
default:
745-
return self.diagnose(Diagnostic(node: keyword, message: UnexpectedTokenKindError(token: keyword)))
741+
return self.diagnose(.unexpectedTokenKind(token: keyword))
746742
}
747743
case .precedenceGroupAssignment(let assignment):
748744
if let current = body.assignment {
@@ -764,7 +760,7 @@ extension ASTGenVisitor {
764760
if let value = BridgedAssociativity(from: token.keywordKind) {
765761
associativityValue = value
766762
} else {
767-
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
763+
self.diagnose(.unexpectedTokenKind(token: token))
768764
associativityValue = .none
769765
}
770766
} else {
@@ -776,7 +772,7 @@ extension ASTGenVisitor {
776772
if token.keywordKind == .true {
777773
assignmentValue = true
778774
} else {
779-
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
775+
self.diagnose(.unexpectedTokenKind(token: token))
780776
assignmentValue = false
781777
}
782778
} else {
@@ -831,7 +827,7 @@ extension ASTGenVisitor {
831827
if let value = BridgedImportKind(from: specifier.keywordKind) {
832828
importKind = value
833829
} else {
834-
self.diagnose(Diagnostic(node: specifier, message: UnexpectedTokenKindError(token: specifier)))
830+
self.diagnose(.unexpectedTokenKind(token: specifier))
835831
importKind = .module
836832
}
837833
} else {

lib/ASTGen/Sources/ASTGen/Diagnostics.swift

Lines changed: 86 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -13,65 +13,90 @@
1313
import SwiftDiagnostics
1414
import SwiftSyntax
1515

16-
protocol ASTGenError: DiagnosticMessage {}
16+
extension ASTGenVisitor {
17+
/// Emits the given ASTGen diagnostic via the C++ diagnostic engine.
18+
func diagnose(_ message: ASTGenDiagnostic, highlights: [Syntax]? = nil, notes: [Note] = [], fixIts: [FixIt] = []) {
19+
self.diagnose(Diagnostic(
20+
node: message.node,
21+
message: message,
22+
highlights: highlights,
23+
notes: notes,
24+
fixIts: fixIts
25+
))
26+
}
1727

18-
extension ASTGenError {
19-
var diagnosticID: MessageID {
20-
MessageID(domain: "ASTGen", id: "\(Self.self)")
28+
/// Emits the given diagnostic via the C++ diagnostic engine.
29+
func diagnose(_ diagnostic: Diagnostic) {
30+
emitDiagnostic(
31+
diagnosticEngine: self.diagnosticEngine,
32+
sourceFileBuffer: self.base,
33+
diagnostic: diagnostic,
34+
diagnosticSeverity: diagnostic.diagMessage.severity
35+
)
2136
}
2237

23-
var severity: DiagnosticSeverity { .error }
38+
/// Emits the given diagnostics via the C++ diagnostic engine.
39+
func diagnoseAll(_ diagnostics: [Diagnostic]) {
40+
diagnostics.forEach(diagnose)
41+
}
2442
}
2543

26-
/// An error emitted when a token is of an unexpected kind.
27-
struct UnexpectedTokenKindError: ASTGenError {
28-
let token: TokenSyntax
29-
private let parent: Syntax
44+
struct ASTGenDiagnostic: DiagnosticMessage {
45+
var node: Syntax
46+
var message: String
47+
var severity: DiagnosticSeverity
48+
var messageID: String
3049

31-
init(token: TokenSyntax) {
32-
guard let parent = token.parent else {
33-
preconditionFailure("Expected a child (not a root) token")
34-
}
50+
var diagnosticID: MessageID {
51+
MessageID(domain: "ASTGen", id: messageID)
52+
}
3553

36-
self.token = token
37-
self.parent = parent
54+
init(node: some SyntaxProtocol, message: String, severity: DiagnosticSeverity = .error, messageID: String) {
55+
self.node = Syntax(node)
56+
self.message = message
57+
self.severity = severity
58+
self.messageID = messageID
3859
}
3960

40-
var message: String {
41-
return """
42-
unexpected token kind for token:
43-
\(self.token.debugDescription)
44-
in parent:
45-
\(self.parent.debugDescription(indentString: " "))
46-
"""
61+
fileprivate init(node: some SyntaxProtocol, message: String, severity: DiagnosticSeverity = .error, function: String = #function) {
62+
// Extract messageID from the function name.
63+
let messageID = String(function.prefix(while: { $0 != "(" }))
64+
self.init(node: node, message: message, severity: severity, messageID: messageID)
4765
}
4866
}
4967

50-
/// An error emitted when an optional child token is unexpectedly nil.
51-
struct MissingChildTokenError: ASTGenError {
52-
let parent: Syntax
53-
let kindOfTokenMissing: TokenKind
68+
extension ASTGenDiagnostic {
69+
/// An error emitted when a token is of an unexpected kind.
70+
static func unexpectedTokenKind(token: TokenSyntax) -> Self {
71+
guard let parent = token.parent else {
72+
preconditionFailure("Expected a child (not a root) token")
73+
}
5474

55-
init(parent: some SyntaxProtocol, kindOfTokenMissing: TokenKind) {
56-
self.parent = Syntax(parent)
57-
self.kindOfTokenMissing = kindOfTokenMissing
75+
return Self(
76+
node: token,
77+
message: """
78+
unexpected token kind for token:
79+
\(token.debugDescription)
80+
in parent:
81+
\(parent.debugDescription(indentString: " "))
82+
"""
83+
)
5884
}
5985

60-
var message: String {
61-
"""
62-
missing child token of kind '\(self.kindOfTokenMissing)' in:
63-
\(parent.debugDescription(indentString: " "))
64-
"""
86+
/// An error emitted when an optional child token is unexpectedly nil.
87+
static func missingChildToken(parent: some SyntaxProtocol, kindOfTokenMissing: TokenKind) -> Self {
88+
Self(
89+
node: parent,
90+
message: """
91+
missing child token of kind '\(kindOfTokenMissing)' in:
92+
\(parent.debugDescription(indentString: " "))
93+
"""
94+
)
6595
}
66-
}
6796

68-
/// An error emitted when a syntax collection entry is encountered that is considered a duplicate of a previous entry
69-
/// per the language grammar.
70-
struct DuplicateSyntaxError: ASTGenError {
71-
let duplicate: Syntax
72-
let original: Syntax
73-
74-
init(duplicate: some SyntaxProtocol, original: some SyntaxProtocol) {
97+
/// An error emitted when a syntax collection entry is encountered that is
98+
/// considered a duplicate of a previous entry per the language grammar.
99+
static func duplicateSyntax(duplicate: some SyntaxProtocol, original: some SyntaxProtocol) -> Self {
75100
precondition(duplicate.kind == original.kind, "Expected duplicate and original to be of same kind")
76101

77102
guard let duplicateParent = duplicate.parent, let originalParent = original.parent,
@@ -80,42 +105,28 @@ struct DuplicateSyntaxError: ASTGenError {
80105
preconditionFailure("Expected a shared syntax collection parent")
81106
}
82107

83-
self.duplicate = Syntax(duplicate)
84-
self.original = Syntax(original)
85-
}
86-
87-
var message: String {
88-
"""
89-
unexpected duplicate syntax in list:
90-
\(duplicate.debugDescription(indentString: " "))
91-
previous syntax:
92-
\(original.debugDescription(indentString: " "))
93-
"""
94-
}
95-
}
96-
97-
struct NonTrivialPatternForAccessorError: ASTGenError {
98-
var message: String {
99-
"getter/setter can only be defined for a single variable"
100-
}
101-
}
102-
103-
struct UnknownAccessorSpecifierError: ASTGenError {
104-
var specifier: TokenSyntax
105-
init(_ specifier: TokenSyntax) {
106-
self.specifier = specifier
108+
return Self(
109+
node: duplicate,
110+
message: """
111+
unexpected duplicate syntax in list:
112+
\(duplicate.debugDescription(indentString: " "))
113+
previous syntax:
114+
\(original.debugDescription(indentString: " "))
115+
"""
116+
)
107117
}
108118

109-
var message: String {
110-
"unknown accessor specifier '\(specifier.text)'"
119+
static func nonTrivialPatternForAccessor(_ pattern: some SyntaxProtocol) -> Self {
120+
Self(
121+
node: pattern,
122+
message: "getter/setter can only be defined for a single variable"
123+
)
111124
}
112-
}
113125

114-
struct RegexParserError: ASTGenError {
115-
var message: String
116-
init(_ message: String) {
117-
self.message = message
126+
static func unknownAccessorSpecifier(_ specifier: TokenSyntax) -> Self {
127+
Self(
128+
node: specifier,
129+
message: "unknown accessor specifier '\(specifier.text)'"
130+
)
118131
}
119-
120-
var severity: DiagnosticSeverity { .error }
121132
}

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,14 +402,10 @@ extension ASTGenVisitor {
402402
func generate(functionCallExpr node: FunctionCallExprSyntax, postfixIfConfigBaseExpr: BridgedExpr? = nil) -> BridgedCallExpr {
403403
if !node.arguments.isEmpty || node.trailingClosure == nil {
404404
if node.leftParen == nil {
405-
self.diagnose(
406-
Diagnostic(node: node, message: MissingChildTokenError(parent: node, kindOfTokenMissing: .leftParen))
407-
)
405+
self.diagnose(.missingChildToken(parent: node, kindOfTokenMissing: .leftParen))
408406
}
409407
if node.rightParen == nil {
410-
self.diagnose(
411-
Diagnostic(node: node, message: MissingChildTokenError(parent: node, kindOfTokenMissing: .rightParen))
412-
)
408+
self.diagnose(.missingChildToken(parent: node, kindOfTokenMissing: .rightParen))
413409
}
414410
}
415411

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ extension ASTGenVisitor {
367367
specifierLoc: self.generateSourceLoc(specifier)
368368
).asTypeRepr
369369
} else {
370-
self.diagnose(Diagnostic(node: specifier, message: UnexpectedTokenKindError(token: specifier)))
370+
self.diagnose(.unexpectedTokenKind(token: specifier))
371371
}
372372
}
373373

0 commit comments

Comments
 (0)