Skip to content

Commit 7f41da9

Browse files
committed
Merge pull request swiftlang#1484 from kimdv/kimdv/add-diagnostic-for-dictionary
Add diagnostic for dictionary
1 parent e9d3460 commit 7f41da9

File tree

2 files changed

+119
-14
lines changed

2 files changed

+119
-14
lines changed

Sources/SwiftParser/Types.swift

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,61 @@ extension Parser {
10521052
)
10531053
)
10541054
} else {
1055-
return self.parseType()
1055+
var result = self.parseType()
1056+
1057+
guard !result.hasError else {
1058+
return result
1059+
}
1060+
1061+
if self.at(.rightSquareBracket) {
1062+
let (unexpectedBeforeRSquareBracket, rightSquareBracket) = self.expect(.rightSquareBracket)
1063+
result = RawTypeSyntax(
1064+
RawArrayTypeSyntax(
1065+
leftSquareBracket: missingToken(.leftSquareBracket),
1066+
elementType: result,
1067+
unexpectedBeforeRSquareBracket,
1068+
rightSquareBracket: rightSquareBracket,
1069+
arena: self.arena
1070+
)
1071+
)
1072+
} else if self.at(.colon) {
1073+
var lookahead = self.lookahead()
1074+
1075+
// We only want to continue with a dictionary if we can parse a colon and a simpletype.
1076+
// Otherwise we can get a wrong diagnostic if we get a Python-style function declaration.
1077+
guard lookahead.consume(if: .colon) != nil && lookahead.canParseSimpleType() else {
1078+
return result
1079+
}
1080+
1081+
let (unexpectedBeforeColon, colon) = self.expect(.colon)
1082+
let secondType = self.parseSimpleType()
1083+
let rightSquareBracket = self.consume(if: .rightSquareBracket) ?? self.missingToken(.rightSquareBracket)
1084+
1085+
result = RawTypeSyntax(
1086+
RawDictionaryTypeSyntax(
1087+
leftSquareBracket: self.missingToken(.leftSquareBracket),
1088+
keyType: result,
1089+
unexpectedBeforeColon,
1090+
colon: colon,
1091+
valueType: secondType,
1092+
rightSquareBracket: rightSquareBracket,
1093+
arena: self.arena
1094+
)
1095+
)
1096+
}
1097+
1098+
var loopProgress = LoopProgressCondition()
1099+
while loopProgress.evaluate(currentToken) {
1100+
if self.at(TokenSpec(.postfixQuestionMark, allowAtStartOfLine: false)) {
1101+
result = RawTypeSyntax(self.parseOptionalType(result))
1102+
} else if self.at(TokenSpec(.exclamationMark, allowAtStartOfLine: false)) {
1103+
result = RawTypeSyntax(self.parseImplicitlyUnwrappedOptionalType(result))
1104+
} else {
1105+
break
1106+
}
1107+
}
1108+
1109+
return result
10561110
}
10571111
}
10581112
}

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,22 +1209,63 @@ final class RecoveryTests: XCTestCase {
12091209
"""
12101210
struct ErrorTypeInVarDeclDictionaryType {
12111211
let a1: String1️⃣:
1212-
let a2: String2️⃣: Int]
1213-
let a3: String3️⃣: [Int]
1214-
let a4: String4️⃣: Int
1212+
let a2: 2️⃣String: Int]
1213+
let a3: 3️⃣String: [Int]4️⃣
1214+
let a4: 5️⃣String: Int6️⃣
1215+
let a4: 7️⃣String: Int]??
12151216
}
12161217
""",
12171218
diagnostics: [
1218-
// TODO: Old parser expected error on line 2: unexpected ':' in type; did you mean to write a dictionary type?, Fix-It replacements: 11 - 11 = '['
1219-
DiagnosticSpec(locationMarker: "1️⃣", message: "consecutive declarations on a line must be separated by ';'"),
1220-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code ':' before variable"),
1221-
// TODO: Old parser expected error on line 3: unexpected ':' in type; did you mean to write a dictionary type?, Fix-It replacements: 11 - 11 = '['
1222-
DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code ': Int]' before variable"),
1223-
// TODO: Old parser expected error on line 4: unexpected ':' in type; did you mean to write a dictionary type?, Fix-It replacements: 11 - 11 = '[', 24 - 24 = ']'
1224-
DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected code ': [Int]' before variable"),
1225-
// TODO: Old parser expected error on line 5: unexpected ':' in type; did you mean to write a dictionary type?, Fix-It replacements: 11 - 11 = '[', 22 - 22 = ']'
1226-
DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code ': Int' in struct"),
1227-
]
1219+
DiagnosticSpec(
1220+
locationMarker: "1️⃣",
1221+
message: "consecutive declarations on a line must be separated by ';'",
1222+
fixIts: ["insert ';'"]
1223+
),
1224+
DiagnosticSpec(
1225+
locationMarker: "1️⃣",
1226+
message: "unexpected code ':' before variable"
1227+
),
1228+
DiagnosticSpec(
1229+
locationMarker: "2️⃣",
1230+
message: "expected '[' to start dictionary type",
1231+
fixIts: ["insert '['"]
1232+
),
1233+
DiagnosticSpec(
1234+
locationMarker: "3️⃣",
1235+
message: "expected '[' to start dictionary type",
1236+
fixIts: ["insert '['"]
1237+
),
1238+
DiagnosticSpec(
1239+
locationMarker: "4️⃣",
1240+
message: "expected ']' to end dictionary type",
1241+
fixIts: ["insert ']'"]
1242+
),
1243+
DiagnosticSpec(
1244+
locationMarker: "5️⃣",
1245+
message: "expected '[' to start dictionary type",
1246+
fixIts: ["insert '['"]
1247+
),
1248+
DiagnosticSpec(
1249+
locationMarker: "6️⃣",
1250+
message: "expected ']' to end dictionary type",
1251+
fixIts: ["insert ']'"]
1252+
),
1253+
DiagnosticSpec(
1254+
locationMarker: "7️⃣",
1255+
message: "expected '[' to start dictionary type",
1256+
fixIts: ["insert '['"]
1257+
),
1258+
1259+
],
1260+
fixedSource: """
1261+
struct ErrorTypeInVarDeclDictionaryType {
1262+
let a1: String;:
1263+
let a2: [String: Int]
1264+
let a3: [String: [Int]]
1265+
let a4: [String: Int]
1266+
let a4: [String: Int]??
1267+
}
1268+
"""
12281269
)
12291270
}
12301271

@@ -2312,4 +2353,14 @@ final class RecoveryTests: XCTestCase {
23122353
"""
23132354
)
23142355
}
2356+
2357+
// https://github.com/apple/swift-syntax/pull/1484/files#r1176740738
2358+
func testRecovery184() {
2359+
assertParse(
2360+
"func foo() -> Int1️⃣:",
2361+
diagnostics: [
2362+
DiagnosticSpec(message: "extraneous code ':' at top level")
2363+
]
2364+
)
2365+
}
23152366
}

0 commit comments

Comments
 (0)