Skip to content

Commit 41a1737

Browse files
committed
Handle DeinitializerDeclSyntax errors in a single diagnostic
1 parent 00dc4d9 commit 41a1737

File tree

13 files changed

+90
-97
lines changed

13 files changed

+90
-97
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ public let DECL_NODES: [Node] = [
19811981
Node(
19821982
kind: .returnClause,
19831983
base: .syntax,
1984-
nameForDiagnostics: nil,
1984+
nameForDiagnostics: "return clause",
19851985
children: [
19861986
Child(
19871987
name: "arrow",

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -788,40 +788,36 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
788788
if shouldSkip(node) {
789789
return .skipChildren
790790
}
791+
792+
var nodes: [SyntaxProtocol] = []
793+
791794
if let unexpected = node.unexpectedBetweenDeinitKeywordAndEffectSpecifiers,
792795
let name = unexpected.presentTokens(satisfying: { $0.tokenKind.isIdentifier == true }).only
793796
{
794-
addDiagnostic(
795-
name,
796-
.deinitCannotHaveName,
797-
fixIts: [
798-
FixIt(message: RemoveNodesFixIt(name), changes: .makeMissing(name))
799-
],
800-
handledNodes: [name.id]
801-
)
797+
nodes += [name]
802798
}
803799
if let unexpected = node.unexpectedBetweenDeinitKeywordAndEffectSpecifiers,
804800
let params = unexpected.compactMap({ $0.as(FunctionParameterClauseSyntax.self) }).only
805801
{
806-
addDiagnostic(
807-
params,
808-
.deinitCannotHaveParameters,
809-
fixIts: [
810-
FixIt(message: RemoveNodesFixIt(params), changes: .makeMissing(params))
811-
],
812-
handledNodes: [params.id]
813-
)
802+
nodes += [params]
814803
}
815804
if let unexpected = node.unexpectedBetweenEffectSpecifiersAndBody,
816805
let returnType = unexpected.compactMap({ $0.as(ReturnClauseSyntax.self) }).only
817806
{
807+
nodes += [returnType]
808+
}
809+
810+
if !nodes.isEmpty {
818811
addDiagnostic(
819-
returnType,
820-
.deinitCannotHaveReturnType,
812+
nodes[0],
813+
DeinitializerSignatureError(nodes: nodes),
821814
fixIts: [
822-
FixIt(message: RemoveNodesFixIt(returnType), changes: .makeMissing(returnType))
815+
FixIt(
816+
message: RemoveNodesFixIt(nodes),
817+
changes: nodes.map { .makeMissing($0) }
818+
)
823819
],
824-
handledNodes: [returnType.id]
820+
handledNodes: nodes.map { $0.id }
825821
)
826822
}
827823

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,9 @@ extension DiagnosticMessage where Self == StaticParserError {
120120
public static var defaultOutsideOfSwitch: Self {
121121
.init("'default' label can only appear inside a 'switch' statement")
122122
}
123-
public static var deinitCannotHaveName: Self {
124-
.init("deinitializers cannot have a name")
125-
}
126-
public static var deinitCannotHaveParameters: Self {
127-
.init("deinitializers cannot have parameters")
128-
}
129123
public static var deinitCannotThrow: Self {
130124
.init("deinitializers cannot throw")
131125
}
132-
public static var deinitCannotHaveReturnType: Self {
133-
.init("deinitializers cannot have return type")
134-
}
135126
public static var editorPlaceholderInSourceFile: Self {
136127
.init("editor placeholder in source file")
137128
}
@@ -305,6 +296,18 @@ public struct CannotParseVersionTuple: ParserError {
305296
}
306297
}
307298

299+
public struct DeinitializerSignatureError: ParserError {
300+
public let nodes: [Syntax]
301+
302+
init(nodes: [any SyntaxProtocol]) {
303+
self.nodes = nodes.map(Syntax.init)
304+
}
305+
306+
public var message: String {
307+
return "deinitializers cannot have \(nodesDescription(nodes, format: true))"
308+
}
309+
}
310+
308311
public struct DuplicateEffectSpecifiers: ParserError {
309312
public let correctSpecifier: TokenSyntax
310313
public let unexpectedSpecifier: TokenSyntax
@@ -706,7 +709,7 @@ public struct RemoveRedundantFixIt: ParserFixIt {
706709
public struct RemoveNodesFixIt: ParserFixIt {
707710
public let nodesToRemove: [Syntax]
708711

709-
init(_ nodesToRemove: [some SyntaxProtocol]) {
712+
init(_ nodesToRemove: [any SyntaxProtocol]) {
710713
self.nodesToRemove = nodesToRemove.map(Syntax.init)
711714
}
712715

Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ extension SyntaxKind {
325325
return "regex literal"
326326
case .repeatStmt:
327327
return "'repeat' statement"
328+
case .returnClause:
329+
return "return clause"
328330
case .returnStmt:
329331
return "'return' statement"
330332
case .sameTypeRequirement:

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ final class DeclarationTests: ParserTestCase {
913913
}
914914
""",
915915
diagnostics: [
916-
DiagnosticSpec(message: "expected '->' and return type in subscript", fixIts: ["insert '->' and return type"])
916+
DiagnosticSpec(message: "expected '->' and return type in return clause", fixIts: ["insert '->' and return type"])
917917
],
918918
fixedSource: """
919919
struct Foo {
@@ -1474,7 +1474,7 @@ final class DeclarationTests: ParserTestCase {
14741474
diagnostics: [
14751475
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected brace before subscript"),
14761476
DiagnosticSpec(locationMarker: "2️⃣", message: "expected parameter clause in subscript", fixIts: ["insert parameter clause"]),
1477-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected '->' and return type in subscript", fixIts: ["insert '->' and return type"]),
1477+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected '->' and return type in return clause", fixIts: ["insert '->' and return type"]),
14781478
],
14791479
fixedSource: """
14801480
}subscript() -> <#type#>

Tests/SwiftParserTest/ExpressionTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ final class ExpressionTests: ParserTestCase {
10111011
DiagnosticSpec(locationMarker: "1️⃣", message: "expected pattern in variable", fixIts: ["insert pattern"]),
10121012
DiagnosticSpec(locationMarker: "2️⃣", message: "expected type in function type", fixIts: ["insert type"]),
10131013
DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code '..' in function type"),
1014-
DiagnosticSpec(locationMarker: "3️⃣", message: "expected return type in function type", fixIts: ["insert return type"]),
1014+
DiagnosticSpec(locationMarker: "3️⃣", message: "expected return type in return clause", fixIts: ["insert return type"]),
10151015
],
10161016
fixedSource: """
10171017
let <#pattern#>:(<#type#>..)-> <#type#>

Tests/SwiftParserTest/StatementTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ final class StatementTests: ParserTestCase {
689689
),
690690
DiagnosticSpec(
691691
locationMarker: "2️⃣",
692-
message: "expected '->' and return type in subscript",
692+
message: "expected '->' and return type in return clause",
693693
fixIts: ["insert '->' and return type"]
694694
),
695695
DiagnosticSpec(

Tests/SwiftParserTest/TypeTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ final class TypeTests: ParserTestCase {
5555
diagnostics: [
5656
DiagnosticSpec(locationMarker: "1️⃣", message: "expected type in function type", fixIts: ["insert type"]),
5757
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '..' in function type"),
58-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected return type in function type", fixIts: ["insert return type"]),
58+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected return type in return clause", fixIts: ["insert return type"]),
5959
],
6060
fixedSource: """
6161
t as(<#type#>..)-> <#type#>

Tests/SwiftParserTest/translated/AsyncTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ final class AsyncTests: ParserTestCase {
149149
}
150150
""",
151151
diagnostics: [
152-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'async' in subscript")
152+
DiagnosticSpec(message: "unexpected code 'async' before return clause")
153153
]
154154
)
155155
}

0 commit comments

Comments
 (0)