Skip to content

Commit 2870c41

Browse files
committed
Add diagnostic for array type
1 parent 7e099ed commit 2870c41

File tree

4 files changed

+66
-84
lines changed

4 files changed

+66
-84
lines changed

Sources/SwiftParser/Types.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,21 @@ extension Parser {
10451045
)
10461046
)
10471047
} else {
1048-
return self.parseType()
1048+
var result = self.parseType()
1049+
if self.at(.rightSquareBracket) {
1050+
let (unexpectedBeforeRSquareBracket, rightSquareBracket) = self.expect(.rightSquareBracket)
1051+
result = RawTypeSyntax(
1052+
RawArrayTypeSyntax(
1053+
leftSquareBracket: missingToken(.leftSquareBracket),
1054+
elementType: result,
1055+
unexpectedBeforeRSquareBracket,
1056+
rightSquareBracket: rightSquareBracket,
1057+
arena: self.arena
1058+
)
1059+
)
1060+
}
1061+
1062+
return result
10491063
}
10501064
}
10511065
}

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,23 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
12321232
return .visitChildren
12331233
}
12341234

1235+
public override func visit(_ node: ArrayTypeSyntax) -> SyntaxVisitorContinueKind {
1236+
if shouldSkip(node) {
1237+
return .skipChildren
1238+
}
1239+
1240+
if node.leftSquareBracket.presence == .missing {
1241+
addDiagnostic(
1242+
node.leftSquareBracket,
1243+
.extraRightBracket,
1244+
fixIts: [.init(message: InsertFixIt(tokenToBeInserted: node.leftSquareBracket), changes: .makePresent(node.leftSquareBracket))],
1245+
handledNodes: [node.leftSquareBracket.id]
1246+
)
1247+
}
1248+
1249+
return .visitChildren
1250+
}
1251+
12351252
//==========================================================================//
12361253
// IMPORTANT: If you are tempted to add a `visit` method here, please //
12371254
// insert it in alphabetical order above //

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ extension DiagnosticMessage where Self == StaticParserError {
131131
public static var expectedSequenceExpressionInForEachLoop: Self {
132132
.init("expected Sequence expression for for-each loop")
133133
}
134+
public static var extraRightBracket: Self {
135+
.init("unexpected ']' in type; did you mean to write an array type?")
136+
}
134137
public static var initializerInPattern: Self {
135138
.init("unexpected initializer in pattern; did you mean to use '='?")
136139
}
@@ -527,6 +530,14 @@ extension FixItMessage where Self == StaticParserFixIt {
527530
}
528531
}
529532

533+
public struct InsertFixIt: ParserFixIt {
534+
public let tokenToBeInserted: TokenSyntax
535+
536+
public var message: String {
537+
"insert '\(tokenToBeInserted.text)'"
538+
}
539+
}
540+
530541
public struct MoveTokensAfterFixIt: ParserFixIt {
531542
/// The token that should be moved
532543
public let movedTokens: [TokenSyntax]

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 23 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,87 +1084,27 @@ final class RecoveryTests: XCTestCase {
10841084
)
10851085
}
10861086

1087-
func testRecovery98a() {
1088-
assertParse(
1089-
"""
1090-
let a1: Swift.Int1️⃣]
1091-
""",
1092-
diagnostics: [
1093-
DiagnosticSpec(message: "extraneous code ']' at top level")
1094-
]
1095-
)
1096-
}
1097-
1098-
func testRecovery98b() {
1099-
assertParse(
1100-
"""
1101-
let a2: Set<Int1️⃣]>
1102-
""",
1103-
diagnostics: [
1104-
DiagnosticSpec(message: "expected '>' to end generic argument clause"),
1105-
DiagnosticSpec(message: "extraneous code ']>' at top level"),
1106-
]
1107-
)
1108-
}
1109-
1110-
func testRecovery98c() {
1111-
assertParse(
1112-
"""
1113-
let a3: Set<Int>1️⃣]
1114-
""",
1115-
diagnostics: [
1116-
// TODO: Old parser expected error on line 4: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 11 - 11 = '['
1117-
DiagnosticSpec(message: "extraneous code ']' at top level")
1118-
]
1119-
)
1120-
}
1121-
1122-
func testRecovery98d() {
1123-
assertParse(
1124-
"""
1125-
let a4: Int1️⃣]?
1126-
""",
1127-
diagnostics: [
1128-
// TODO: Old parser expected error on line 5: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 11 - 11 = '['
1129-
DiagnosticSpec(message: "extraneous code ']?' at top level")
1130-
]
1131-
)
1132-
}
1133-
1134-
func testRecovery98e() {
1135-
assertParse(
1136-
"""
1137-
let a5: Int?1️⃣]
1138-
""",
1139-
diagnostics: [
1140-
// TODO: Old parser expected error on line 6: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 11 - 11 = '['
1141-
DiagnosticSpec(message: "extraneous code ']' at top level")
1142-
]
1143-
)
1144-
}
1145-
1146-
func testRecovery98f() {
1147-
assertParse(
1148-
"""
1149-
let a6: [Int]1️⃣]
1150-
""",
1151-
diagnostics: [
1152-
// TODO: Old parser expected error on line 7: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 11 - 11 = '['
1153-
DiagnosticSpec(message: "extraneous code ']' at top level")
1154-
]
1155-
)
1156-
}
1157-
1158-
func testRecovery98g() {
1159-
assertParse(
1160-
"""
1161-
let a7: [String: Int]1️⃣]
1162-
""",
1163-
diagnostics: [
1164-
// TODO: Old parser expected error on line 8: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 11 - 11 = '['
1165-
DiagnosticSpec(message: "extraneous code ']' at top level")
1166-
]
1167-
)
1087+
func testRecovery98() {
1088+
let testCases: [UInt: (testCase: String, fixedSource: String)] = [
1089+
#line: ("let a1: 1️⃣Swift.Int]", "let a1: [Swift.Int]"),
1090+
#line: ("let a2: Set<1️⃣Int]>", "let a2: Set<[Int]>"),
1091+
#line: ("let a3: 1️⃣Set<Int>]", "let a3: [Set<Int>]"),
1092+
#line: ("let a4: 1️⃣Int]?", "let a4: [Int]?"),
1093+
#line: ("let a5: 1️⃣Int?]", "let a5: [Int?]"),
1094+
#line: ("let a6: 1️⃣[Int]]", "let a6: [[Int]]"),
1095+
#line: ("let a7: [String: 1️⃣Int]]", "let a7: [[String: Int]]"),
1096+
]
1097+
1098+
for (line, testCase) in testCases {
1099+
assertParse(
1100+
testCase.testCase,
1101+
diagnostics: [
1102+
DiagnosticSpec(message: "unexpected ']' in type; did you mean to write an array type?", fixIts: ["insert '['"], line: line)
1103+
],
1104+
fixedSource: testCase.fixedSource,
1105+
line: line
1106+
)
1107+
}
11681108
}
11691109

11701110
func testRecovery99() {
@@ -1198,7 +1138,7 @@ final class RecoveryTests: XCTestCase {
11981138
func foo() -> Int1️⃣[ {
11991139
return [0]
12001140
} 2️⃣
1201-
func bar() -> Int3️⃣] {
1141+
func bar() -> 3️⃣Int] {
12021142
return [0]
12031143
}
12041144
4️⃣}
@@ -1207,7 +1147,7 @@ final class RecoveryTests: XCTestCase {
12071147
DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct"),
12081148
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array"),
12091149
// TODO: Old parser expected error on line 5: unexpected ']' in type; did you mean to write an array type?, Fix-It replacements: 17 - 17 = '['
1210-
DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected code ']' in function"),
1150+
DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected ']' in type; did you mean to write an array type?"),
12111151
DiagnosticSpec(locationMarker: "4️⃣", message: "extraneous brace at top level"),
12121152
]
12131153
)

0 commit comments

Comments
 (0)