Skip to content

Commit 0a98797

Browse files
committed
Add diagnostics for missing modifier in operator declaration & update test cases
1 parent 7e099ed commit 0a98797

File tree

5 files changed

+35
-13
lines changed

5 files changed

+35
-13
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, unexpectedBeforeOperatorKeyword == 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
@@ -871,6 +871,17 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
871871
if shouldSkip(node) {
872872
return .skipChildren
873873
}
874+
875+
if let modifier = node.modifiers,
876+
modifier.isMissingAllTokens == true
877+
{
878+
addDiagnostic(
879+
modifier,
880+
.missingModifierForOperatorDecl,
881+
handledNodes: [modifier.id]
882+
)
883+
}
884+
874885
if let unexpected = node.unexpectedAfterOperatorPrecedenceAndTypes,
875886
unexpected.contains(where: { $0.is(PrecedenceGroupAttributeListSyntax.self) }) == true
876887
{

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ extension DiagnosticMessage where Self == StaticParserError {
167167
public static var missingConformanceRequirement: Self {
168168
.init("expected ':' or '==' to indicate a conformance or same-type requirement")
169169
}
170+
public static var missingModifierForOperatorDecl: Self {
171+
.init("operator must be declared as 'prefix', 'postfix', or 'infix'")
172+
}
170173
public static var misspelledAsync: Self {
171174
.init("expected async specifier; did you mean 'async'?")
172175
}

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: 8 additions & 8 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
}

0 commit comments

Comments
 (0)