Skip to content

Commit 36b0f23

Browse files
authored
Merge pull request #1548 from kimdv/kimdv/add-notes-to-assertion
Add notes to assertion
2 parents d167613 + 9d62ac1 commit 36b0f23

28 files changed

+1665
-470
lines changed

Tests/SwiftParserTest/Assertions.swift

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ struct DiagnosticSpec {
239239
/// If not `nil`, assert that the highlighted range has this content.
240240
let highlight: String?
241241
/// If not `nil`, assert that the diagnostic contains notes with these messages.
242-
let notes: [NoteSpec]?
242+
let notes: [NoteSpec]
243243
/// If not `nil`, assert that the diagnostic contains fix-its with these messages.
244244
/// Use the `fixedSource` parameter on `AssertParse` to check that applying the Fix-It yields the expected result.
245245
let fixIts: [String]
@@ -254,7 +254,7 @@ struct DiagnosticSpec {
254254
message: String?,
255255
severity: DiagnosticSeverity = .error,
256256
highlight: String? = nil,
257-
notes: [NoteSpec]? = nil,
257+
notes: [NoteSpec] = [],
258258
fixIts: [String] = [],
259259
file: StaticString = #file,
260260
line: UInt = #line
@@ -406,20 +406,18 @@ func assertDiagnostic<T: SyntaxProtocol>(
406406
line: spec.line
407407
)
408408
}
409-
if let notes = spec.notes {
410-
if diag.notes.count != notes.count {
411-
XCTFail(
412-
"""
413-
Expected \(notes.count) notes but received \(diag.notes.count):
414-
\(diag.notes.map(\.debugDescription).joined(separator: "\n"))
415-
""",
416-
file: spec.file,
417-
line: spec.line
418-
)
419-
} else {
420-
for (note, expectedNote) in zip(diag.notes, notes) {
421-
assertNote(note, in: tree, markerLocations: markerLocations, expected: expectedNote)
422-
}
409+
if diag.notes.count != spec.notes.count {
410+
XCTFail(
411+
"""
412+
Expected \(spec.notes.count) notes but received \(diag.notes.count):
413+
\(diag.notes.map(\.debugDescription).joined(separator: "\n"))
414+
""",
415+
file: spec.file,
416+
line: spec.line
417+
)
418+
} else {
419+
for (note, expectedNote) in zip(diag.notes, spec.notes) {
420+
assertNote(note, in: tree, markerLocations: markerLocations, expected: expectedNote)
423421
}
424422
}
425423

Tests/SwiftParserTest/AttributeTests.swift

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,20 @@ final class AttributeTests: XCTestCase {
1818
func testMissingArgumentToAttribute() {
1919
assertParse(
2020
"""
21-
@_dynamicReplacement(1️⃣
21+
@_dynamicReplacementℹ️(1️⃣
2222
func 2️⃣test_dynamic_replacement_for2() {
2323
}
2424
""",
2525
diagnostics: [
26-
DiagnosticSpec(message: "expected argument for '@_dynamicReplacement' attribute", fixIts: ["insert attribute argument"]),
27-
DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]),
26+
DiagnosticSpec(
27+
message: "expected argument for '@_dynamicReplacement' attribute",
28+
fixIts: ["insert attribute argument"]
29+
),
30+
DiagnosticSpec(
31+
message: "expected ')' to end attribute",
32+
notes: [NoteSpec(message: "to match this opening '('")],
33+
fixIts: ["insert ')'"]
34+
),
2835
],
2936
fixedSource: """
3037
@_dynamicReplacement(for: <#identifier#>)
@@ -37,14 +44,23 @@ final class AttributeTests: XCTestCase {
3744
func testMissingGenericTypeToAttribute() {
3845
assertParse(
3946
"""
40-
@differentiable(reverse wrt1️⃣,where T2️⃣
47+
@differentiableℹ️(reverse wrt1️⃣,where T2️⃣
4148
func podcastPlaybackSpeed() {
4249
}
4350
""",
4451
diagnostics: [
45-
DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' and parameters in '@differentiable' argument", fixIts: ["insert ':' and parameters"]),
52+
DiagnosticSpec(
53+
locationMarker: "1️⃣",
54+
message: "expected ':' and parameters in '@differentiable' argument",
55+
fixIts: ["insert ':' and parameters"]
56+
),
4657
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ':' or '==' to indicate a conformance or same-type requirement"),
47-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end attribute", fixIts: ["insert ')'"]),
58+
DiagnosticSpec(
59+
locationMarker: "2️⃣",
60+
message: "expected ')' to end attribute",
61+
notes: [NoteSpec(message: "to match this opening '('")],
62+
fixIts: ["insert ')'"]
63+
),
4864
],
4965
fixedSource: """
5066
@differentiable(reverse wrt: <#identifier#>,where T)
@@ -57,12 +73,22 @@ final class AttributeTests: XCTestCase {
5773
func testMissingClosingParenToAttribute() {
5874
assertParse(
5975
"""
60-
@_specialize(e1️⃣
76+
@_specializeℹ️(e1️⃣
6177
""",
6278
diagnostics: [
63-
DiagnosticSpec(message: "expected ':' in attribute argument", fixIts: ["insert ':'"]),
64-
DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]),
65-
DiagnosticSpec(message: "expected declaration after attribute", fixIts: ["insert declaration"]),
79+
DiagnosticSpec(
80+
message: "expected ':' in attribute argument",
81+
fixIts: ["insert ':'"]
82+
),
83+
DiagnosticSpec(
84+
message: "expected ')' to end attribute",
85+
notes: [NoteSpec(message: "to match this opening '('")],
86+
fixIts: ["insert ')'"]
87+
),
88+
DiagnosticSpec(
89+
message: "expected declaration after attribute",
90+
fixIts: ["insert declaration"]
91+
),
6692
],
6793
fixedSource: """
6894
@_specialize(e:) <#declaration#>

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 132 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,20 @@ final class DeclarationTests: XCTestCase {
132132
"""
133133
)
134134
assertParse(
135-
"class B<where g1️⃣",
135+
"class Bℹ️<where g1️⃣",
136136
diagnostics: [
137-
DiagnosticSpec(message: "expected ':' or '==' to indicate a conformance or same-type requirement"),
138-
DiagnosticSpec(message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]),
139-
DiagnosticSpec(message: "expected member block in class", fixIts: ["insert member block"]),
137+
DiagnosticSpec(
138+
message: "expected ':' or '==' to indicate a conformance or same-type requirement"
139+
),
140+
DiagnosticSpec(
141+
message: "expected '>' to end generic parameter clause",
142+
notes: [NoteSpec(message: "to match this opening '<'")],
143+
fixIts: ["insert '>'"]
144+
),
145+
DiagnosticSpec(
146+
message: "expected member block in class",
147+
fixIts: ["insert member block"]
148+
),
140149
],
141150
fixedSource: """
142151
class B<where g> {
@@ -193,11 +202,23 @@ final class DeclarationTests: XCTestCase {
193202
)
194203

195204
assertParse(
196-
"protocol P{1️⃣{}case2️⃣",
205+
"protocol Pℹ️{1️⃣{}case2️⃣",
197206
diagnostics: [
198-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '{}' before enum case"),
199-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected identifier in enum case", fixIts: ["insert identifier"]),
200-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end protocol", fixIts: ["insert '}'"]),
207+
DiagnosticSpec(
208+
locationMarker: "1️⃣",
209+
message: "unexpected code '{}' before enum case"
210+
),
211+
DiagnosticSpec(
212+
locationMarker: "2️⃣",
213+
message: "expected identifier in enum case",
214+
fixIts: ["insert identifier"]
215+
),
216+
DiagnosticSpec(
217+
locationMarker: "2️⃣",
218+
message: "expected '}' to end protocol",
219+
notes: [NoteSpec(message: "to match this opening '{'")],
220+
fixIts: ["insert '}'"]
221+
),
201222
],
202223
fixedSource: """
203224
protocol P{{}case <#identifier#>
@@ -672,9 +693,13 @@ final class DeclarationTests: XCTestCase {
672693

673694
func testMissingClosingParenInFunctionSignature() {
674695
assertParse(
675-
"func test(first second: Int1️⃣",
696+
"func testℹ️(first second: Int1️⃣",
676697
diagnostics: [
677-
DiagnosticSpec(message: "expected ')' to end parameter clause", fixIts: ["insert ')'"])
698+
DiagnosticSpec(
699+
message: "expected ')' to end parameter clause",
700+
notes: [NoteSpec(message: "to match this opening '('")],
701+
fixIts: ["insert ')'"]
702+
)
678703
],
679704
fixedSource: """
680705
func test(first second: Int)
@@ -814,15 +839,31 @@ final class DeclarationTests: XCTestCase {
814839
func testExpressionMember() {
815840
assertParse(
816841
"""
817-
struct S {1️⃣
818-
/2️⃣ ###line 25 "line-directive.swift"3️⃣
819-
4️⃣}
842+
struct S 1️⃣{2️⃣
843+
3️⃣/4️⃣ ###line 25 "line-directive.swift"5️⃣
844+
6️⃣}
820845
""",
821846
diagnostics: [
822-
DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]),
823-
DiagnosticSpec(locationMarker: "2️⃣", message: "bare slash regex literal may not start with space"),
824-
DiagnosticSpec(locationMarker: "3️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/\'"]),
825-
DiagnosticSpec(locationMarker: "4️⃣", message: "extraneous brace at top level"),
847+
DiagnosticSpec(
848+
locationMarker: "2️⃣",
849+
message: "expected '}' to end struct",
850+
notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")],
851+
fixIts: ["insert '}'"]
852+
),
853+
DiagnosticSpec(
854+
locationMarker: "4️⃣",
855+
message: "bare slash regex literal may not start with space"
856+
),
857+
DiagnosticSpec(
858+
locationMarker: "5️⃣",
859+
message: "expected '/' to end regex literal",
860+
notes: [NoteSpec(locationMarker: "3️⃣", message: "to match this opening '/'")],
861+
fixIts: ["insert '/\'"]
862+
),
863+
DiagnosticSpec(
864+
locationMarker: "6️⃣",
865+
message: "extraneous brace at top level"
866+
),
826867
],
827868
fixedSource: """
828869
struct S {
@@ -915,7 +956,7 @@ final class DeclarationTests: XCTestCase {
915956

916957
func testDontRecoverFromDeclKeyword() {
917958
assertParse(
918-
"func foo(first second 1️⃣third 2️⃣struct3️⃣: Int4️⃣) {}",
959+
"func fooℹ️(first second 1️⃣third 2️⃣struct3️⃣: Int4️⃣) {}",
919960
substructure: Syntax(
920961
FunctionParameterSyntax(
921962
firstName: .identifier("first"),
@@ -925,10 +966,26 @@ final class DeclarationTests: XCTestCase {
925966
)
926967
),
927968
diagnostics: [
928-
DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]),
929-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]),
930-
DiagnosticSpec(locationMarker: "3️⃣", message: "expected identifier in struct", fixIts: ["insert identifier"]),
931-
DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code ')' in struct"),
969+
DiagnosticSpec(
970+
locationMarker: "1️⃣",
971+
message: "expected ':' in parameter",
972+
fixIts: ["insert ':'"]
973+
),
974+
DiagnosticSpec(
975+
locationMarker: "2️⃣",
976+
message: "expected ')' to end parameter clause",
977+
notes: [NoteSpec(message: "to match this opening '('")],
978+
fixIts: ["insert ')'"]
979+
),
980+
DiagnosticSpec(
981+
locationMarker: "3️⃣",
982+
message: "expected identifier in struct",
983+
fixIts: ["insert identifier"]
984+
),
985+
DiagnosticSpec(
986+
locationMarker: "4️⃣",
987+
message: "unexpected code ')' in struct"
988+
),
932989
],
933990
fixedSource: """
934991
func foo(first second: third)struct <#identifier#>: Int) {}
@@ -975,9 +1032,21 @@ final class DeclarationTests: XCTestCase {
9751032
)
9761033
),
9771034
diagnostics: [
978-
DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]),
979-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array type", fixIts: ["insert ']'"]),
980-
DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code 'fourth: Int' in parameter clause"),
1035+
DiagnosticSpec(
1036+
locationMarker: "1️⃣",
1037+
message: "expected ':' in parameter",
1038+
fixIts: ["insert ':'"]
1039+
),
1040+
DiagnosticSpec(
1041+
locationMarker: "2️⃣",
1042+
message: "expected ']' to end array type",
1043+
notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '['")],
1044+
fixIts: ["insert ']'"]
1045+
),
1046+
DiagnosticSpec(
1047+
locationMarker: "2️⃣",
1048+
message: "unexpected code 'fourth: Int' in parameter clause"
1049+
),
9811050
],
9821051
fixedSource: """
9831052
func foo(first second: [third]fourth: Int) {}
@@ -988,7 +1057,7 @@ final class DeclarationTests: XCTestCase {
9881057
func testDontRecoverIfNewlineIsBeforeColon() {
9891058
assertParse(
9901059
"""
991-
func foo(first second 1️⃣third2️⃣
1060+
func fooℹ️(first second 1️⃣third2️⃣
9921061
3️⃣: Int) {}
9931062
""",
9941063
substructure: Syntax(
@@ -1000,9 +1069,21 @@ final class DeclarationTests: XCTestCase {
10001069
)
10011070
),
10021071
diagnostics: [
1003-
DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]),
1004-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]),
1005-
DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous code ': Int) {}' at top level"),
1072+
DiagnosticSpec(
1073+
locationMarker: "1️⃣",
1074+
message: "expected ':' in parameter",
1075+
fixIts: ["insert ':'"]
1076+
),
1077+
DiagnosticSpec(
1078+
locationMarker: "2️⃣",
1079+
message: "expected ')' to end parameter clause",
1080+
notes: [NoteSpec(message: "to match this opening '('")],
1081+
fixIts: ["insert ')'"]
1082+
),
1083+
DiagnosticSpec(
1084+
locationMarker: "3️⃣",
1085+
message: "extraneous code ': Int) {}' at top level"
1086+
),
10061087
],
10071088
fixedSource: """
10081089
func foo(first second: third)
@@ -1261,13 +1342,30 @@ final class DeclarationTests: XCTestCase {
12611342
func testStandaloneAtSignInGenericParameter() {
12621343
assertParse(
12631344
"""
1264-
struct U<@1️⃣
1345+
struct U1️⃣<@2️⃣
12651346
""",
12661347
diagnostics: [
1267-
DiagnosticSpec(message: "expected name in attribute", fixIts: ["insert name"]),
1268-
DiagnosticSpec(message: "expected name in generic parameter", fixIts: ["insert name"]),
1269-
DiagnosticSpec(message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]),
1270-
DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]),
1348+
DiagnosticSpec(
1349+
locationMarker: "2️⃣",
1350+
message: "expected name in attribute",
1351+
fixIts: ["insert name"]
1352+
),
1353+
DiagnosticSpec(
1354+
locationMarker: "2️⃣",
1355+
message: "expected name in generic parameter",
1356+
fixIts: ["insert name"]
1357+
),
1358+
DiagnosticSpec(
1359+
locationMarker: "2️⃣",
1360+
message: "expected '>' to end generic parameter clause",
1361+
notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '<'")],
1362+
fixIts: ["insert '>'"]
1363+
),
1364+
DiagnosticSpec(
1365+
locationMarker: "2️⃣",
1366+
message: "expected member block in struct",
1367+
fixIts: ["insert member block"]
1368+
),
12711369
],
12721370
fixedSource: """
12731371
struct U<@<#type#> <#identifier#>> {

0 commit comments

Comments
 (0)