Skip to content

Commit 7d5684e

Browse files
committed
(WIP) Add diagnostics for missing modifier in operator declaration & update test cases
1 parent 9764512 commit 7d5684e

File tree

5 files changed

+38
-14
lines changed

5 files changed

+38
-14
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1964,9 +1964,16 @@ extension Parser {
19641964
} else {
19651965
unexpectedAtEnd = nil
19661966
}
1967+
1968+
var modifiers: RawModifierListSyntax? = attrs.modifiers
1969+
if modifiers == nil {
1970+
let missedModifier = RawDeclModifierSyntax(name: self.missingToken(.prefix), detail: nil, arena: self.arena)
1971+
modifiers = RawModifierListSyntax(elements: [missedModifier], arena: self.arena)
1972+
}
1973+
19671974
return RawOperatorDeclSyntax(
19681975
attributes: attrs.attributes,
1969-
modifiers: attrs.modifiers,
1976+
modifiers: modifiers,
19701977
unexpectedBeforeOperatorKeyword,
19711978
operatorKeyword: operatorKeyword,
19721979
unexpectedBeforeName,

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,17 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
855855
if shouldSkip(node) {
856856
return .skipChildren
857857
}
858+
859+
if let modifier = node.modifiers,
860+
modifier.isMissingAllTokens == true
861+
{
862+
addDiagnostic(
863+
modifier,
864+
.missingModifierForOperatorDecl,
865+
handledNodes: [modifier.id]
866+
)
867+
}
868+
858869
if let unexpected = node.unexpectedAfterOperatorPrecedenceAndTypes,
859870
unexpected.contains(where: { $0.is(PrecedenceGroupAttributeListSyntax.self) }) == true
860871
{

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ extension DiagnosticMessage where Self == StaticParserError {
164164
public static var missingConformanceRequirement: Self {
165165
.init("expected ':' or '==' to indicate a conformance or same-type requirement")
166166
}
167+
public static var missingModifierForOperatorDecl: Self {
168+
.init("operator must be declared as 'prefix', 'postfix', or 'infix'")
169+
}
167170
public static var misspelledAsync: Self {
168171
.init("expected async specifier; did you mean 'async'?")
169172
}

Tests/SwiftParserTest/Parser+EntryTests.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class EntryTests: XCTestCase {
4747

4848
func testRemainderUnexpectedDoesntOverrideExistingUnexpected() throws {
4949
AssertParse(
50-
"operator 1️⃣test 2️⃣{} other tokens",
50+
"1️⃣operator 2️⃣test 3️⃣{} other tokens",
5151
{ DeclSyntax.parse(from: &$0) },
5252
substructure: Syntax(
5353
UnexpectedNodesSyntax([
@@ -58,10 +58,11 @@ public class EntryTests: XCTestCase {
5858
TokenSyntax.identifier("tokens"),
5959
])
6060
),
61-
substructureAfterMarker: "2️⃣",
61+
substructureAfterMarker: "3️⃣",
6262
diagnostics: [
63-
DiagnosticSpec(locationMarker: "1️⃣", message: "'test' is considered an identifier and must not appear within an operator name"),
64-
DiagnosticSpec(locationMarker: "2️⃣", message: "operator should not be declared with body"),
63+
DiagnosticSpec(locationMarker: "1️⃣", message: "operator must be declared as 'prefix', 'postfix', or 'infix'"),
64+
DiagnosticSpec(locationMarker: "2️⃣", message: "'test' is considered an identifier and must not appear within an operator name"),
65+
DiagnosticSpec(locationMarker: "3️⃣", message: "operator should not be declared with body"),
6566
]
6667
)
6768
}

Tests/SwiftParserTest/translated/OperatorDeclTests.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,34 +117,34 @@ final class OperatorDeclTests: XCTestCase {
117117
func testOperatorDecl6() {
118118
AssertParse(
119119
"""
120-
operator ++*** : A
120+
1️⃣operator ++*** : A
121121
""",
122122
diagnostics: [
123-
// TODO: Old parser expected error on line 1: operator must be declared as 'prefix', 'postfix', or 'infix'
123+
DiagnosticSpec(message: "operator must be declared as 'prefix', 'postfix', or 'infix'")
124124
]
125125
)
126126
}
127127

128128
func testOperatorDecl7() {
129129
AssertParse(
130130
"""
131-
operator +*+++ 1️⃣{ }
131+
1️⃣operator +*+++ 2️⃣{ }
132132
""",
133133
diagnostics: [
134-
// TODO: Old parser expected error on line 1: operator must be declared as 'prefix', 'postfix', or 'infix'
135-
DiagnosticSpec(message: "operator should not be declared with body")
134+
DiagnosticSpec(locationMarker: "1️⃣", message: "operator must be declared as 'prefix', 'postfix', or 'infix'"),
135+
DiagnosticSpec(locationMarker: "2️⃣", message: "operator should not be declared with body"),
136136
]
137137
)
138138
}
139139

140140
func testOperatorDecl8() {
141141
AssertParse(
142142
"""
143-
operator +*++* : A 1️⃣{ }
143+
1️⃣operator +*++* : A 2️⃣{ }
144144
""",
145145
diagnostics: [
146-
// TODO: Old parser expected error on line 1: operator must be declared as 'prefix', 'postfix', or 'infix'
147-
DiagnosticSpec(message: "operator should not be declared with body")
146+
DiagnosticSpec(locationMarker: "1️⃣", message: "operator must be declared as 'prefix', 'postfix', or 'infix'"),
147+
DiagnosticSpec(locationMarker: "2️⃣", message: "operator should not be declared with body"),
148148
]
149149
)
150150
}
@@ -167,7 +167,9 @@ final class OperatorDeclTests: XCTestCase {
167167
prefix operator %%+
168168
""",
169169
diagnostics: [
170-
DiagnosticSpec(message: "unexpected code before operator declaration")
170+
DiagnosticSpec(message: "operator must be declared as 'prefix', 'postfix', or 'infix'"),
171+
// TODO: should be "unexpected code before operator declaration" here
172+
DiagnosticSpec(message: "unexpected code in operator declaration"),
171173
]
172174
)
173175
}

0 commit comments

Comments
 (0)