diff --git a/Tests/SwiftParserTest/Assertions.swift b/Tests/SwiftParserTest/Assertions.swift index b58979a5440..5d0f4bcecb1 100644 --- a/Tests/SwiftParserTest/Assertions.swift +++ b/Tests/SwiftParserTest/Assertions.swift @@ -239,7 +239,7 @@ struct DiagnosticSpec { /// If not `nil`, assert that the highlighted range has this content. let highlight: String? /// If not `nil`, assert that the diagnostic contains notes with these messages. - let notes: [NoteSpec]? + let notes: [NoteSpec] /// If not `nil`, assert that the diagnostic contains fix-its with these messages. /// Use the `fixedSource` parameter on `AssertParse` to check that applying the Fix-It yields the expected result. let fixIts: [String] @@ -254,7 +254,7 @@ struct DiagnosticSpec { message: String?, severity: DiagnosticSeverity = .error, highlight: String? = nil, - notes: [NoteSpec]? = nil, + notes: [NoteSpec] = [], fixIts: [String] = [], file: StaticString = #file, line: UInt = #line @@ -406,20 +406,18 @@ func assertDiagnostic( line: spec.line ) } - if let notes = spec.notes { - if diag.notes.count != notes.count { - XCTFail( - """ - Expected \(notes.count) notes but received \(diag.notes.count): - \(diag.notes.map(\.debugDescription).joined(separator: "\n")) - """, - file: spec.file, - line: spec.line - ) - } else { - for (note, expectedNote) in zip(diag.notes, notes) { - assertNote(note, in: tree, markerLocations: markerLocations, expected: expectedNote) - } + if diag.notes.count != spec.notes.count { + XCTFail( + """ + Expected \(spec.notes.count) notes but received \(diag.notes.count): + \(diag.notes.map(\.debugDescription).joined(separator: "\n")) + """, + file: spec.file, + line: spec.line + ) + } else { + for (note, expectedNote) in zip(diag.notes, spec.notes) { + assertNote(note, in: tree, markerLocations: markerLocations, expected: expectedNote) } } diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 7abfd8235c0..46fc15627ea 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -18,13 +18,20 @@ final class AttributeTests: XCTestCase { func testMissingArgumentToAttribute() { assertParse( """ - @_dynamicReplacement(1️⃣ + @_dynamicReplacementℹ️(1️⃣ func 2️⃣test_dynamic_replacement_for2() { } """, diagnostics: [ - DiagnosticSpec(message: "expected argument for '@_dynamicReplacement' attribute", fixIts: ["insert attribute argument"]), - DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]), + DiagnosticSpec( + message: "expected argument for '@_dynamicReplacement' attribute", + fixIts: ["insert attribute argument"] + ), + DiagnosticSpec( + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: """ @_dynamicReplacement(for: <#identifier#>) @@ -37,14 +44,23 @@ final class AttributeTests: XCTestCase { func testMissingGenericTypeToAttribute() { assertParse( """ - @differentiable(reverse wrt1️⃣,where T2️⃣ + @differentiableℹ️(reverse wrt1️⃣,where T2️⃣ func podcastPlaybackSpeed() { } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' and parameters in '@differentiable' argument", fixIts: ["insert ':' and parameters"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected ':' and parameters in '@differentiable' argument", + fixIts: ["insert ':' and parameters"] + ), DiagnosticSpec(locationMarker: "2️⃣", message: "expected ':' or '==' to indicate a conformance or same-type requirement"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end attribute", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: """ @differentiable(reverse wrt: <#identifier#>,where T) @@ -57,12 +73,22 @@ final class AttributeTests: XCTestCase { func testMissingClosingParenToAttribute() { assertParse( """ - @_specialize(e1️⃣ + @_specializeℹ️(e1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected ':' in attribute argument", fixIts: ["insert ':'"]), - DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]), - DiagnosticSpec(message: "expected declaration after attribute", fixIts: ["insert declaration"]), + DiagnosticSpec( + message: "expected ':' in attribute argument", + fixIts: ["insert ':'"] + ), + DiagnosticSpec( + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + message: "expected declaration after attribute", + fixIts: ["insert declaration"] + ), ], fixedSource: """ @_specialize(e:) <#declaration#> diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index ff80025b001..36f4ae707f3 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -132,11 +132,20 @@ final class DeclarationTests: XCTestCase { """ ) assertParse( - "class B' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in class", fixIts: ["insert member block"]), + DiagnosticSpec( + message: "expected ':' or '==' to indicate a conformance or same-type requirement" + ), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "expected member block in class", + fixIts: ["insert member block"] + ), ], fixedSource: """ class B { @@ -193,11 +202,23 @@ final class DeclarationTests: XCTestCase { ) assertParse( - "protocol P{1️⃣{}case2️⃣", + "protocol Pℹ️{1️⃣{}case2️⃣", diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '{}' before enum case"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected identifier in enum case", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end protocol", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '{}' before enum case" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected identifier in enum case", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end protocol", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: """ protocol P{{}case <#identifier#> @@ -672,9 +693,13 @@ final class DeclarationTests: XCTestCase { func testMissingClosingParenInFunctionSignature() { assertParse( - "func test(first second: Int1️⃣", + "func testℹ️(first second: Int1️⃣", diagnostics: [ - DiagnosticSpec(message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' to end parameter clause", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: """ func test(first second: Int) @@ -814,15 +839,31 @@ final class DeclarationTests: XCTestCase { func testExpressionMember() { assertParse( """ - struct S {1️⃣ - /2️⃣ ###line 25 "line-directive.swift"3️⃣ - 4️⃣} + struct S 1️⃣{2️⃣ + 3️⃣/4️⃣ ###line 25 "line-directive.swift"5️⃣ + 6️⃣} """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "bare slash regex literal may not start with space"), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/\'"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "extraneous brace at top level"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "bare slash regex literal may not start with space" + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "expected '/' to end regex literal", + notes: [NoteSpec(locationMarker: "3️⃣", message: "to match this opening '/'")], + fixIts: ["insert '/\'"] + ), + DiagnosticSpec( + locationMarker: "6️⃣", + message: "extraneous brace at top level" + ), ], fixedSource: """ struct S { @@ -915,7 +956,7 @@ final class DeclarationTests: XCTestCase { func testDontRecoverFromDeclKeyword() { assertParse( - "func foo(first second 1️⃣third 2️⃣struct3️⃣: Int4️⃣) {}", + "func fooℹ️(first second 1️⃣third 2️⃣struct3️⃣: Int4️⃣) {}", substructure: Syntax( FunctionParameterSyntax( firstName: .identifier("first"), @@ -925,10 +966,26 @@ final class DeclarationTests: XCTestCase { ) ), diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected identifier in struct", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code ')' in struct"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected ':' in parameter", + fixIts: ["insert ':'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected identifier in struct", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code ')' in struct" + ), ], fixedSource: """ func foo(first second: third)struct <#identifier#>: Int) {} @@ -975,9 +1032,21 @@ final class DeclarationTests: XCTestCase { ) ), diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array type", fixIts: ["insert ']'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code 'fourth: Int' in parameter clause"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected ':' in parameter", + fixIts: ["insert ':'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ']' to end array type", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code 'fourth: Int' in parameter clause" + ), ], fixedSource: """ func foo(first second: [third]fourth: Int) {} @@ -988,7 +1057,7 @@ final class DeclarationTests: XCTestCase { func testDontRecoverIfNewlineIsBeforeColon() { assertParse( """ - func foo(first second 1️⃣third2️⃣ + func fooℹ️(first second 1️⃣third2️⃣ 3️⃣: Int) {} """, substructure: Syntax( @@ -1000,9 +1069,21 @@ final class DeclarationTests: XCTestCase { ) ), diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ':' in parameter", fixIts: ["insert ':'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous code ': Int) {}' at top level"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected ':' in parameter", + fixIts: ["insert ':'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "extraneous code ': Int) {}' at top level" + ), ], fixedSource: """ func foo(first second: third) @@ -1261,13 +1342,30 @@ final class DeclarationTests: XCTestCase { func testStandaloneAtSignInGenericParameter() { assertParse( """ - struct U<@1️⃣ + struct U1️⃣<@2️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected name in attribute", fixIts: ["insert name"]), - DiagnosticSpec(message: "expected name in generic parameter", fixIts: ["insert name"]), - DiagnosticSpec(message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected name in attribute", + fixIts: ["insert name"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected name in generic parameter", + fixIts: ["insert name"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected member block in struct", + fixIts: ["insert member block"] + ), ], fixedSource: """ struct U<@<#type#> <#identifier#>> { diff --git a/Tests/SwiftParserTest/ExpressionTests.swift b/Tests/SwiftParserTest/ExpressionTests.swift index 5c025a1c635..affbe886b95 100644 --- a/Tests/SwiftParserTest/ExpressionTests.swift +++ b/Tests/SwiftParserTest/ExpressionTests.swift @@ -338,12 +338,21 @@ final class ExpressionTests: XCTestCase { assertParse( """ - [1️⃣ + ℹ️[1️⃣ ,2️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected value in array element", fixIts: ["insert value"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected value in array element", + fixIts: ["insert value"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), ], fixedSource: """ [<#expression#> @@ -353,11 +362,18 @@ final class ExpressionTests: XCTestCase { assertParse( """ - ([1:1️⃣) + (ℹ️[1:1️⃣) """, diagnostics: [ - DiagnosticSpec(message: "expected value in dictionary element", fixIts: ["insert value"]), - DiagnosticSpec(message: "expected ']' to end dictionary", fixIts: ["insert ']'"]), + DiagnosticSpec( + message: "expected value in dictionary element", + fixIts: ["insert value"] + ), + DiagnosticSpec( + message: "expected ']' to end dictionary", + notes: [NoteSpec(message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), ], fixedSource: """ ([1: <#expression#>]) @@ -434,11 +450,21 @@ final class ExpressionTests: XCTestCase { assertParse( #""" - "\(()1️⃣ + 1️⃣"\2️⃣(()3️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "\(())" @@ -583,10 +609,14 @@ final class ExpressionTests: XCTestCase { assertParse( ##""" - """""1️⃣ + ℹ️"""""1️⃣ """##, diagnostics: [ - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]) + DiagnosticSpec( + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ) ], fixedSource: ##""" """""""" @@ -643,10 +673,18 @@ final class ExpressionTests: XCTestCase { ) assertParse( - ###""1️⃣\2️⃣"###, + ###"ℹ️"1️⃣\2️⃣"###, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "invalid escape sequence in literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "invalid escape sequence in literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ###""" "\" @@ -706,11 +744,20 @@ final class ExpressionTests: XCTestCase { func testStringBogusClosingDelimiters() { assertParse( ##""" - \1️⃣\(2️⃣ + \1️⃣\ℹ️(2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected root in key path", fixIts: ["insert root"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end tuple type", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected root in key path", + fixIts: ["insert root"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end tuple type", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: ##""" \<#type#>\() @@ -725,10 +772,14 @@ final class ExpressionTests: XCTestCase { assertParse( #""" - "1️⃣ + ℹ️"1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]) + DiagnosticSpec( + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ) ], fixedSource: #""" "" @@ -737,10 +788,14 @@ final class ExpressionTests: XCTestCase { assertParse( #""" - "'1️⃣ + ℹ️"'1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]) + DiagnosticSpec( + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ) ], fixedSource: #""" "'" @@ -789,17 +844,36 @@ final class ExpressionTests: XCTestCase { func testBogusKeypathBaseRecovery() { assertParse( #""" - func nestThoseIfs() { + func nestThoseIfs() 1️⃣{ \n - if false != true { + if false != true 2️⃣{ \n - print1️⃣ "\(i)\"\n2️⃣ + print3️⃣ 4️⃣"\(i)\"\n5️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end 'if' statement", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end function", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "4️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "expected '}' to end 'if' statement", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: #""" func nestThoseIfs() { @@ -813,10 +887,19 @@ final class ExpressionTests: XCTestCase { ) assertParse( - "#keyPath((b:1️⃣)2️⃣", + "#keyPathℹ️((b:1️⃣)2️⃣", diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected value in tuple", fixIts: ["insert value"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end macro expansion", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected value in tuple", + fixIts: ["insert value"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end macro expansion", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: """ #keyPath((b: <#expression#>)) @@ -1020,14 +1103,31 @@ final class ExpressionTests: XCTestCase { func testNewlineInInterpolationOfSingleLineString() { assertParse( #""" - "test \(label:1️⃣ - foo2️⃣)" + 1️⃣"test \2️⃣(label:3️⃣ + foo4️⃣)" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected value in string literal", fixIts: ["insert value"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"extraneous code ')"' at top level"#), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected value in string literal", + fixIts: ["insert value"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"extraneous code ')"' at top level"# + ), ], fixedSource: #""" "test \(label: <#expression#>)" @@ -1039,7 +1139,7 @@ final class ExpressionTests: XCTestCase { func testUnterminatedStringLiteral() { assertParse( """ - "This is unterminated1️⃣ + ℹ️"This is unterminated1️⃣ x """, substructure: Syntax( @@ -1052,7 +1152,11 @@ final class ExpressionTests: XCTestCase { ) ), diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]) + DiagnosticSpec( + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ) ], fixedSource: """ "This is unterminated" @@ -1203,10 +1307,14 @@ final class ExpressionTests: XCTestCase { line 1 1️⃣ line 2 - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" """ @@ -1788,12 +1896,22 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString1() { assertParse( #""" - "abc1️⃣ - "2️⃣ + 1️⃣"abc2️⃣ + 3️⃣"4️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "abc" @@ -1805,12 +1923,22 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString2() { assertParse( #""" - "1️⃣ - "2️⃣ + 1️⃣"2️⃣ + 3️⃣"4️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "" @@ -1822,13 +1950,27 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString3() { assertParse( #""" - "abc1️⃣ - \(def)2️⃣"3️⃣ + 1️⃣"abc2️⃣ + \(def)3️⃣"4️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "abc" @@ -1840,13 +1982,26 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString4() { assertParse( #""" - "abc\(def1️⃣2️⃣ - 3️⃣)" + 1️⃣"abc\2️⃣(def3️⃣ + 4️⃣)" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "3️⃣", message: #"extraneous code ')"' at top level"#), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"extraneous code ')"' at top level"# + ), ], fixedSource: #""" "abc\(def)" @@ -1858,13 +2013,25 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString5() { assertParse( #""" - "abc\(1️⃣2️⃣ + ℹ️"abc\(1️⃣2️⃣ def3️⃣)" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected value and ')' in string literal", fixIts: ["insert value and ')'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "3️⃣", message: #"extraneous code ')"' at top level"#), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected value and ')' in string literal", + fixIts: ["insert value and ')'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"extraneous code ')"' at top level"# + ), ], fixedSource: #""" "abc\(<#expression#>)" @@ -1876,14 +2043,31 @@ final class StatementExpressionTests: XCTestCase { func testUnterminatedString6() { assertParse( #""" - "abc1️⃣\2️⃣ - (def)3️⃣"4️⃣ + 1️⃣"abc2️⃣\3️⃣ + (def)4️⃣"5️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "invalid escape sequence in literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "3️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "4️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "invalid escape sequence in literal" + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "4️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "abc\" @@ -1917,9 +2101,22 @@ final class StatementExpressionTests: XCTestCase { abc2️⃣"#3️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: ##"expected '"#' to end string literal"##, fixIts: [##"insert '"#'"##]), - DiagnosticSpec(locationMarker: "2️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: ##"expected '"#' to end string literal"##, + fixIts: [##"insert '"#'"##] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "2️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" #""# @@ -1932,11 +2129,20 @@ final class StatementExpressionTests: XCTestCase { assertParse( #""" #"abc1️⃣ - "#2️⃣ + ℹ️"#2️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: ##"expected '"#' to end string literal"##, fixIts: [##"insert '"#'"##]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: ##"expected '"#' to end string literal"##, + fixIts: [##"insert '"#'"##] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" #"abc"# diff --git a/Tests/SwiftParserTest/RegexLiteralTests.swift b/Tests/SwiftParserTest/RegexLiteralTests.swift index 794b74b1546..7804b678b4a 100644 --- a/Tests/SwiftParserTest/RegexLiteralTests.swift +++ b/Tests/SwiftParserTest/RegexLiteralTests.swift @@ -75,10 +75,14 @@ final class RegexLiteralTests: XCTestCase { func testUnterminated2() { assertParse( #""" - /1️⃣ + ℹ️/1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: #""" // @@ -117,10 +121,14 @@ final class RegexLiteralTests: XCTestCase { func testUnterminated5() { assertParse( #""" - #//1️⃣ + ℹ️#//1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '#' to end regex literal", fixIts: ["insert '#'"]) + DiagnosticSpec( + message: "expected '#' to end regex literal", + notes: [NoteSpec(message: "to match this opening '#'")], + fixIts: ["insert '#'"] + ) ], fixedSource: #""" #//# @@ -131,10 +139,14 @@ final class RegexLiteralTests: XCTestCase { func testUnterminated6() { assertParse( #""" - #///1️⃣ + ℹ️#///1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '#' to end regex literal", fixIts: ["insert '#'"]) + DiagnosticSpec( + message: "expected '#' to end regex literal", + notes: [NoteSpec(message: "to match this opening '#'")], + fixIts: ["insert '#'"] + ) ], fixedSource: #""" #///# @@ -145,7 +157,7 @@ final class RegexLiteralTests: XCTestCase { func testUnterminated7() { assertParse( #""" - #/#1️⃣ + ℹ️#/#1️⃣ """#, diagnostics: [ DiagnosticSpec(message: "expected '/#' to end regex literal", fixIts: ["insert '/#'"]) @@ -173,10 +185,14 @@ final class RegexLiteralTests: XCTestCase { func testUnterminated9() { assertParse( #""" - #/##/1️⃣ + ℹ️#/##/1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '#' to end regex literal", fixIts: ["insert '#'"]) + DiagnosticSpec( + message: "expected '#' to end regex literal", + notes: [NoteSpec(message: "to match this opening '#'")], + fixIts: ["insert '#'"] + ) ], fixedSource: #""" #/##/# diff --git a/Tests/SwiftParserTest/StatementTests.swift b/Tests/SwiftParserTest/StatementTests.swift index 4b503ce689d..70122ec42bf 100644 --- a/Tests/SwiftParserTest/StatementTests.swift +++ b/Tests/SwiftParserTest/StatementTests.swift @@ -697,10 +697,14 @@ final class StatementTests: XCTestCase { // https://github.com/apple/swift-syntax/issues/1247 assertParse( """ - if p{""1️⃣ + if pℹ️{""1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '}' to end 'if' statement", fixIts: ["insert '}'"]) + DiagnosticSpec( + message: "expected '}' to end 'if' statement", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ) ], fixedSource: """ if p{"" @@ -712,13 +716,30 @@ final class StatementTests: XCTestCase { func testRecoveryInFrontOfAccessorIntroducer() { assertParse( """ - subscript(1️⃣{2️⃣@self _modify + subscript1️⃣(2️⃣{3️⃣@self _modify """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '->' and return type in subscript", fixIts: ["insert '->' and return type"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end subscript", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "extraneous code '@self _modify' at top level"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '->' and return type in subscript", + fixIts: ["insert '->' and return type"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected '}' to end subscript", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "extraneous code '@self _modify' at top level" + ), ], fixedSource: """ subscript() -> <#type#> { diff --git a/Tests/SwiftParserTest/TypeTests.swift b/Tests/SwiftParserTest/TypeTests.swift index cb8f709eb17..272e266bed8 100644 --- a/Tests/SwiftParserTest/TypeTests.swift +++ b/Tests/SwiftParserTest/TypeTests.swift @@ -94,12 +94,24 @@ final class TypeTests: XCTestCase { ) assertParse( - "{[1️⃣class]in2️⃣", + "ℹ️{[1️⃣class]in2️⃣", { ExprSyntax.parse(from: &$0) }, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected identifier in closure capture item", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected 'class' keyword in closure capture signature"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end closure", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected identifier in closure capture item", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected 'class' keyword in closure capture signature" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end closure", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: """ {[<#identifier#>class]in diff --git a/Tests/SwiftParserTest/translated/ActorTests.swift b/Tests/SwiftParserTest/translated/ActorTests.swift index a0098ebd1cc..037f0391895 100644 --- a/Tests/SwiftParserTest/translated/ActorTests.swift +++ b/Tests/SwiftParserTest/translated/ActorTests.swift @@ -21,7 +21,10 @@ final class ActorTests: XCTestCase { actor MyActor11️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected member block in actor", fixIts: ["insert member block"]) + DiagnosticSpec( + message: "expected member block in actor", + fixIts: ["insert member block"] + ) ], fixedSource: """ actor MyActor1 { diff --git a/Tests/SwiftParserTest/translated/AsyncTests.swift b/Tests/SwiftParserTest/translated/AsyncTests.swift index 370e0789dc0..c8c617e5c35 100644 --- a/Tests/SwiftParserTest/translated/AsyncTests.swift +++ b/Tests/SwiftParserTest/translated/AsyncTests.swift @@ -29,7 +29,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal3() throws 1️⃣async { }", diagnostics: [ - DiagnosticSpec(message: "'async' must precede 'throws'", fixIts: ["move 'async' in front of 'throws'"]) + DiagnosticSpec( + message: "'async' must precede 'throws'", + fixIts: ["move 'async' in front of 'throws'"] + ) ], fixedSource: "func asyncGlobal3() async throws { }" ) @@ -39,7 +42,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal3(fn: () throws -> Int) rethrows 1️⃣async { }", diagnostics: [ - DiagnosticSpec(message: "'async' must precede 'rethrows'", fixIts: ["move 'async' in front of 'rethrows'"]) + DiagnosticSpec( + message: "'async' must precede 'rethrows'", + fixIts: ["move 'async' in front of 'rethrows'"] + ) ], fixedSource: "func asyncGlobal3(fn: () throws -> Int) async rethrows { }" ) @@ -49,7 +55,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal4() -> Int 1️⃣async { }", diagnostics: [ - DiagnosticSpec(message: "'async' must preceed '->'", fixIts: ["move 'async' in front of '->'"]) + DiagnosticSpec( + message: "'async' must preceed '->'", + fixIts: ["move 'async' in front of '->'"] + ) ], fixedSource: "func asyncGlobal4() async -> Int { }" ) @@ -59,7 +68,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal5() -> Int 1️⃣async throws { }", diagnostics: [ - DiagnosticSpec(message: "'async throws' must preceed '->'", fixIts: ["move 'async throws' in front of '->'"]) + DiagnosticSpec( + message: "'async throws' must preceed '->'", + fixIts: ["move 'async throws' in front of '->'"] + ) ], fixedSource: "func asyncGlobal5() async throws -> Int { }" ) @@ -69,7 +81,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal6() -> Int 1️⃣throws async { }", diagnostics: [ - DiagnosticSpec(message: "'throws async' must preceed '->'", fixIts: ["move 'throws async' in front of '->'"]) + DiagnosticSpec( + message: "'throws async' must preceed '->'", + fixIts: ["move 'throws async' in front of '->'"] + ) ], fixedSource: "func asyncGlobal6() async throws -> Int { }" ) @@ -79,7 +94,10 @@ final class AsyncTests: XCTestCase { assertParse( "func asyncGlobal7() throws -> Int 1️⃣async { }", diagnostics: [ - DiagnosticSpec(message: "'async' must preceed '->'", fixIts: ["move 'async' in front of '->'"]) + DiagnosticSpec( + message: "'async' must preceed '->'", + fixIts: ["move 'async' in front of '->'"] + ) ], fixedSource: "func asyncGlobal7() async throws -> Int { }" ) @@ -88,12 +106,25 @@ final class AsyncTests: XCTestCase { func testAsync8() { assertParse( """ - func asyncGlobal8() async throws 1️⃣async -> 2️⃣async Int 3️⃣async {} + func asyncGlobal8() ℹ️async throws 1️⃣async -> 2️⃣async Int 3️⃣async {} """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "'async' has already been specified", fixIts: ["remove redundant 'async'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "'async' must preceed '->'", fixIts: ["remove redundant 'async'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "'async' must preceed '->'", fixIts: ["remove redundant 'async'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "'async' has already been specified", + notes: [NoteSpec(message: "'async' declared here")], + fixIts: ["remove redundant 'async'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "'async' must preceed '->'", + fixIts: ["remove redundant 'async'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "'async' must preceed '->'", + fixIts: ["remove redundant 'async'"] + ), ], fixedSource: """ func asyncGlobal8() async throws -> Int {} @@ -118,7 +149,11 @@ final class AsyncTests: XCTestCase { } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "deinitializers cannot have a name", fixIts: ["remove 'async'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "deinitializers cannot have a name", + fixIts: ["remove 'async'"] + ), DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code 'async' in subscript"), ], fixedSource: """ @@ -158,7 +193,10 @@ final class AsyncTests: XCTestCase { assertParse( "typealias AsyncFunc3 = () throws 1️⃣async -> ()", diagnostics: [ - DiagnosticSpec(message: "'async' must precede 'throws'", fixIts: ["move 'async' in front of 'throws'"]) + DiagnosticSpec( + message: "'async' must precede 'throws'", + fixIts: ["move 'async' in front of 'throws'"] + ) ], fixedSource: "typealias AsyncFunc3 = () async throws -> ()" ) @@ -184,7 +222,10 @@ final class AsyncTests: XCTestCase { assertParse( "let _ = [() throws 1️⃣async -> ()]()", diagnostics: [ - DiagnosticSpec(message: "'async' must precede 'throws'", fixIts: ["move 'async' in front of 'throws'"]) + DiagnosticSpec( + message: "'async' must precede 'throws'", + fixIts: ["move 'async' in front of 'throws'"] + ) ], fixedSource: "let _ = [() async throws -> ()]()" ) @@ -196,7 +237,10 @@ final class AsyncTests: XCTestCase { let _ = [() -> 1️⃣async ()]() """, diagnostics: [ - DiagnosticSpec(message: "'async' must preceed '->'", fixIts: ["move 'async' in front of '->'"]) + DiagnosticSpec( + message: "'async' must preceed '->'", + fixIts: ["move 'async' in front of '->'"] + ) ], fixedSource: """ let _ = [() async -> ()]() diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift index 5705816c546..6f4dbc40d99 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift @@ -353,12 +353,19 @@ final class AvailabilityQueryTests: XCTestCase { func testAvailabilityQuery27() { assertParse( """ - if #available(OSX 10.51, 1️⃣{ + if #availableℹ️(OSX 10.51, 1️⃣{ } """, diagnostics: [ - DiagnosticSpec(message: "expected version restriction in availability argument", fixIts: ["insert version restriction"]), - DiagnosticSpec(message: "expected ')' to end availability condition", fixIts: ["insert ')'"]), + DiagnosticSpec( + message: "expected version restriction in availability argument", + fixIts: ["insert version restriction"] + ), + DiagnosticSpec( + message: "expected ')' to end availability condition", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: """ if #available(OSX 10.51, <#identifier#>) { diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift index 4f23ab006ad..e89c8613fc7 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift @@ -354,7 +354,7 @@ final class AvailabilityQueryUnavailabilityTests: XCTestCase { func testAvailabilityQueryUnavailability22() { assertParse( """ - if #unavailable(OSX 10.51, 1️⃣{ + if #unavailableℹ️(OSX 10.51, 1️⃣{ } """, diagnostics: [ @@ -364,6 +364,7 @@ final class AvailabilityQueryUnavailabilityTests: XCTestCase { ), DiagnosticSpec( message: "expected ')' to end availability condition", + notes: [NoteSpec(message: "to match this opening '('")], fixIts: ["insert ')'"] ), ], diff --git a/Tests/SwiftParserTest/translated/DeprecatedWhereTests.swift b/Tests/SwiftParserTest/translated/DeprecatedWhereTests.swift index 277f64acaaa..d431a6ab729 100644 --- a/Tests/SwiftParserTest/translated/DeprecatedWhereTests.swift +++ b/Tests/SwiftParserTest/translated/DeprecatedWhereTests.swift @@ -158,14 +158,34 @@ final class DeprecatedWhereTests: XCTestCase { func testDeprecatedWhere12() { assertParse( """ - func testCombinedConstraintsOld where T: ProtoC4️⃣>(x: T) {} + func testCombinedConstraintsOldℹ️ where T: ProtoC4️⃣>(x: T) {} """, diagnostics: [ - DiagnosticSpec(locationMarker: "2️⃣", message: "expected inherited type in generic parameter", fixIts: ["insert inherited type"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected parameter clause in function signature", fixIts: ["insert parameter clause"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected identifier in protocol", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code '>(x: T)' in protocol"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected inherited type in generic parameter", + fixIts: ["insert inherited type"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected parameter clause in function signature", + fixIts: ["insert parameter clause"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected identifier in protocol", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code '>(x: T)' in protocol" + ), ], fixedSource: """ func testCombinedConstraintsOld>()protocol <#identifier#> where T: ProtoC>(x: T) {} @@ -176,14 +196,34 @@ final class DeprecatedWhereTests: XCTestCase { func testDeprecatedWhere13() { assertParse( """ - func testCombinedConstraintsOld where T: ProtoC4️⃣>(x: T) where T: ProtoD {} + func testCombinedConstraintsOldℹ️ where T: ProtoC4️⃣>(x: T) where T: ProtoD {} """, diagnostics: [ - DiagnosticSpec(locationMarker: "2️⃣", message: "expected inherited type in generic parameter", fixIts: ["insert inherited type"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected parameter clause in function signature", fixIts: ["insert parameter clause"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected identifier in protocol", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code '>(x: T) where T: ProtoD' in protocol"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected inherited type in generic parameter", + fixIts: ["insert inherited type"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected parameter clause in function signature", + fixIts: ["insert parameter clause"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected identifier in protocol", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code '>(x: T) where T: ProtoD' in protocol" + ), ], fixedSource: """ func testCombinedConstraintsOld>()protocol <#identifier#> where T: ProtoC>(x: T) where T: ProtoD {} diff --git a/Tests/SwiftParserTest/translated/DiagnoseDynamicReplacementTests.swift b/Tests/SwiftParserTest/translated/DiagnoseDynamicReplacementTests.swift index 8a0283c5909..6f95868f186 100644 --- a/Tests/SwiftParserTest/translated/DiagnoseDynamicReplacementTests.swift +++ b/Tests/SwiftParserTest/translated/DiagnoseDynamicReplacementTests.swift @@ -45,19 +45,24 @@ final class DiagnoseDynamicReplacementTests: XCTestCase { func testDiagnoseDynamicReplacement3() { assertParse( """ - @_dynamicReplacement(1️⃣ + @_dynamicReplacementℹ️(1️⃣ func test_dynamic_replacement_for2() { } """, diagnostics: [ DiagnosticSpec(message: "expected argument for '@_dynamicReplacement' attribute", fixIts: ["insert attribute argument"]), - DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]), + DiagnosticSpec( + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: """ @_dynamicReplacement(for: <#identifier#>) func test_dynamic_replacement_for2() { } """ + ) } diff --git a/Tests/SwiftParserTest/translated/ErrorsTests.swift b/Tests/SwiftParserTest/translated/ErrorsTests.swift index e57eecaaa80..ebc1393b925 100644 --- a/Tests/SwiftParserTest/translated/ErrorsTests.swift +++ b/Tests/SwiftParserTest/translated/ErrorsTests.swift @@ -198,12 +198,25 @@ final class ErrorsTests: XCTestCase { func testErrors13() { assertParse( """ - func dupThrows1() throws 1️⃣rethrows -> 2️⃣throws Int 3️⃣throw {} + func dupThrows1() ℹ️throws 1️⃣rethrows -> 2️⃣throws Int 3️⃣throw {} """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "'rethrows' conflicts with 'throws'", fixIts: ["remove redundant 'rethrows'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "'throws' must preceed '->'", fixIts: ["remove redundant 'throws'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "'throw' must preceed '->'", fixIts: ["remove redundant 'throw'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "'rethrows' conflicts with 'throws'", + notes: [NoteSpec(message: "'throws' declared here")], + fixIts: ["remove redundant 'rethrows'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "'throws' must preceed '->'", + fixIts: ["remove redundant 'throws'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "'throw' must preceed '->'", + fixIts: ["remove redundant 'throw'"] + ), ], fixedSource: """ func dupThrows1() throws -> Int {} @@ -217,7 +230,10 @@ final class ErrorsTests: XCTestCase { func dupThrows2(_ f: () throws -> 1️⃣rethrows Int) {} """, diagnostics: [ - DiagnosticSpec(message: "'rethrows' must preceed '->'", fixIts: ["remove redundant 'rethrows'"]) + DiagnosticSpec( + message: "'rethrows' must preceed '->'", + fixIts: ["remove redundant 'rethrows'"] + ) ], fixedSource: """ func dupThrows2(_ f: () throws -> Int) {} @@ -228,10 +244,14 @@ final class ErrorsTests: XCTestCase { func testErrors15a() { assertParse( """ - _ = { () 1️⃣try throws in } + _ = { () 1️⃣try ℹ️throws in } """, diagnostics: [ - DiagnosticSpec(message: "'try' conflicts with 'throws'", fixIts: ["remove redundant 'try'"]) + DiagnosticSpec( + message: "'try' conflicts with 'throws'", + notes: [NoteSpec(message: "'throws' declared here")], + fixIts: ["remove redundant 'try'"] + ) ], fixedSource: """ _ = { () throws in } @@ -245,7 +265,10 @@ final class ErrorsTests: XCTestCase { _ = { () throws -> Int 1️⃣throws in } """, diagnostics: [ - DiagnosticSpec(message: "'throws' must preceed '->'", fixIts: ["remove redundant 'throws'"]) + DiagnosticSpec( + message: "'throws' must preceed '->'", + fixIts: ["remove redundant 'throws'"] + ) ], fixedSource: """ _ = { () throws -> Int in } @@ -451,7 +474,10 @@ final class ErrorsTests: XCTestCase { func fixitAwait2() throws 1️⃣await -> Int { } """, diagnostics: [ - DiagnosticSpec(message: "'await' must precede 'throws'", fixIts: ["move 'await' in front of 'throws'"]) + DiagnosticSpec( + message: "'await' must precede 'throws'", + fixIts: ["move 'await' in front of 'throws'"] + ) ], fixedSource: """ func fixitAwait2() async throws -> Int { } @@ -549,10 +575,14 @@ final class ErrorsTests: XCTestCase { func testAwaitBetwenAsyncAndThrows() { assertParse( """ - func fixitAwait2() async 1️⃣await throws -> Int { } + func fixitAwait2() ℹ️async 1️⃣await throws -> Int { } """, diagnostics: [ - DiagnosticSpec(message: "'await' conflicts with 'async'", fixIts: ["remove redundant 'await'"]) + DiagnosticSpec( + message: "'await' conflicts with 'async'", + notes: [NoteSpec(message: "'async' declared here")], + fixIts: ["remove redundant 'await'"] + ) ], fixedSource: """ func fixitAwait2() async throws -> Int { } @@ -563,10 +593,14 @@ final class ErrorsTests: XCTestCase { func testAsyncAwait() { assertParse( """ - func fixitAwait2() async 1️⃣await -> Int { } + func fixitAwait2() ℹ️async 1️⃣await -> Int { } """, diagnostics: [ - DiagnosticSpec(message: "'await' conflicts with 'async'", fixIts: ["remove redundant 'await'"]) + DiagnosticSpec( + message: "'await' conflicts with 'async'", + notes: [NoteSpec(message: "'async' declared here")], + fixIts: ["remove redundant 'await'"] + ) ], fixedSource: """ func fixitAwait2() async -> Int { } diff --git a/Tests/SwiftParserTest/translated/ForwardSlashRegexSkippingInvalidTests.swift b/Tests/SwiftParserTest/translated/ForwardSlashRegexSkippingInvalidTests.swift index 361f098f823..3b7335df54e 100644 --- a/Tests/SwiftParserTest/translated/ForwardSlashRegexSkippingInvalidTests.swift +++ b/Tests/SwiftParserTest/translated/ForwardSlashRegexSkippingInvalidTests.swift @@ -59,12 +59,20 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( """ func e() { - _ = /1️⃣ }2️⃣ + _ = ℹ️/1️⃣ }2️⃣ } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "bare slash regex literal may not start with space"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "bare slash regex literal may not start with space" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ), ], fixedSource: """ func e() { @@ -78,12 +86,20 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( """ func f() { - _ = /1️⃣ {2️⃣ + _ = ℹ️/1️⃣ {2️⃣ } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "bare slash regex literal may not start with space"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "bare slash regex literal may not start with space" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ), ], fixedSource: """ func f() { @@ -121,12 +137,21 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( #""" func i() { - _ = /x1️⃣ "[abc] {2️⃣ + _ = /x1️⃣ ℹ️"[abc] {2️⃣ } """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" func i() { @@ -140,11 +165,15 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( """ func j() { - _ = /^ [abc] {1️⃣ + _ = ℹ️/^ [abc] {1️⃣ } """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ func j() { @@ -158,11 +187,15 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( #""" func k() { - _ = /^ "[abc] {1️⃣ + _ = ℹ️/^ "[abc] {1️⃣ } """#, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: #""" func k() { @@ -176,11 +209,15 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( """ func l() { - _ = /^ } abc {1️⃣ + _ = ℹ️/^ } abc {1️⃣ } """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ func l() { @@ -194,14 +231,25 @@ final class ForwardSlashRegexSkippingInvalidTests: XCTestCase { assertParse( #""" func m() { - _ = /1️⃣ "2️⃣ + _ = ℹ️/1️⃣ "2️⃣ } 3️⃣} """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "bare slash regex literal may not start with space"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous brace at top level"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "bare slash regex literal may not start with space" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "extraneous brace at top level" + ), ], fixedSource: #""" func m() { diff --git a/Tests/SwiftParserTest/translated/ForwardSlashRegexTests.swift b/Tests/SwiftParserTest/translated/ForwardSlashRegexTests.swift index 37e41e03feb..c47c48f5a79 100644 --- a/Tests/SwiftParserTest/translated/ForwardSlashRegexTests.swift +++ b/Tests/SwiftParserTest/translated/ForwardSlashRegexTests.swift @@ -202,10 +202,14 @@ final class ForwardSlashRegexTests: XCTestCase { func testForwardSlashRegex28() { assertParse( """ - _ = /^)1️⃣ + _ = ℹ️/^)1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ _ = /^)/ @@ -1151,11 +1155,15 @@ final class ForwardSlashRegexTests: XCTestCase { _ = qux(/, 1) / 2 do { _ = qux(/, "(") / 2 - _ = qux(/, "(")/1️⃣2 + _ = quxℹ️(/, "(")/1️⃣2 } """#, diagnostics: [ - DiagnosticSpec(message: "expected ')' to end function call", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' to end function call", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: #""" _ = qux(/, 1) / 2 @@ -1316,10 +1324,14 @@ final class ForwardSlashRegexTests: XCTestCase { func testForwardSlashRegex139() { assertParse( """ - _ = /1️⃣ + _ = ℹ️/1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ _ = // @@ -1330,10 +1342,14 @@ final class ForwardSlashRegexTests: XCTestCase { func testForwardSlashRegex140() { assertParse( """ - _ = /)1️⃣ + _ = ℹ️/)1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ _ = /)/ @@ -1459,8 +1475,17 @@ final class ForwardSlashRegexTests: XCTestCase { _ = ^/"/1️⃣"2️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" _ = ^/"/; "" @@ -1474,8 +1499,18 @@ final class ForwardSlashRegexTests: XCTestCase { _ = ^/"[/1️⃣"2️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" _ = ^/"[/; "" @@ -1566,11 +1601,16 @@ final class ForwardSlashRegexTests: XCTestCase { // There are intentionally trailing spaces here assertParse( """ - _ = /1️⃣ 2️⃣ + _ = ℹ️/1️⃣ 2️⃣ """, diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "bare slash regex literal may not start with space"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '/' to end regex literal", fixIts: ["insert '/'"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ), ], fixedSource: """ _ = / / @@ -1582,10 +1622,14 @@ final class ForwardSlashRegexTests: XCTestCase { // There are intentionally trailing spaces here assertParse( """ - _ = /^ 1️⃣ + _ = ℹ️/^ 1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '/' to end regex literal", fixIts: ["insert '/'"]) + DiagnosticSpec( + message: "expected '/' to end regex literal", + notes: [NoteSpec(message: "to match this opening '/'")], + fixIts: ["insert '/'"] + ) ], fixedSource: """ _ = /^ / diff --git a/Tests/SwiftParserTest/translated/ImplicitGetterIncompleteTests.swift b/Tests/SwiftParserTest/translated/ImplicitGetterIncompleteTests.swift index 7fc0f31b991..eef4aeb0058 100644 --- a/Tests/SwiftParserTest/translated/ImplicitGetterIncompleteTests.swift +++ b/Tests/SwiftParserTest/translated/ImplicitGetterIncompleteTests.swift @@ -35,14 +35,24 @@ final class ImplicitGetterIncompleteTests: XCTestCase { assertParse( #""" // Would trigger assertion when AST verifier checks source ranges ("child source range not contained within its parent") - func test2() { - var a : Int { + func test2() 1️⃣{ + var a : Int 2️⃣{ switch i { - }1️⃣ + }3️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '}' to end variable", fixIts: ["insert '}'"]), - DiagnosticSpec(message: "expected '}' to end function", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected '}' to end variable", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: #""" // Would trigger assertion when AST verifier checks source ranges ("child source range not contained within its parent") diff --git a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift index 527b5332de5..337c344a742 100644 --- a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift +++ b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift @@ -42,11 +42,15 @@ final class InvalidIfExprTests: XCTestCase { func testInvalidIfExpr3() { assertParse( """ - (a ? b ? c : d1️⃣ + ℹ️(a ? b ? c : d1️⃣ """, diagnostics: [ DiagnosticSpec(message: "expected ':' and expression after '? ...' in ternary expression", fixIts: ["insert ':' and expression"]), - DiagnosticSpec(message: "expected ')' to end tuple", fixIts: ["insert ')'"]), + DiagnosticSpec( + message: "expected ')' to end tuple", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: "(a ? b ? c : d: <#expression#>)" ) diff --git a/Tests/SwiftParserTest/translated/InvalidTests.swift b/Tests/SwiftParserTest/translated/InvalidTests.swift index 4ada6972a96..b411b4f91a6 100644 --- a/Tests/SwiftParserTest/translated/InvalidTests.swift +++ b/Tests/SwiftParserTest/translated/InvalidTests.swift @@ -141,12 +141,16 @@ final class InvalidTests: XCTestCase { assertParse( """ func foo() { - runAction(SKAction.sequence()1️⃣ + runActionℹ️(SKAction.sequence()1️⃣ skview! } """, diagnostics: [ - DiagnosticSpec(message: "expected ')' to end function call", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' to end function call", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: """ func foo() { @@ -236,13 +240,21 @@ final class InvalidTests: XCTestCase { // rdar://18926814 assertParse( ##""" - func test4() { + func test4() ℹ️{ let abc = 123 _ = " >> \( abc 1️⃣} ) << "2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected brace in string literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end function", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected brace in string literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: ##""" func test4() { @@ -257,13 +269,22 @@ final class InvalidTests: XCTestCase { // rdar://problem/18507467 assertParse( """ - func d(_ b: 1️⃣String 2️⃣-> 3️⃣() -> T4️⃣) {} + func dℹ️(_ b: 1️⃣String 2️⃣-> 3️⃣() -> T4️⃣) {} """, diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "expected '(' to start function type", fixIts: ["insert '('"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' in function type", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ')' in function type", + fixIts: ["insert ')'"] + ), DiagnosticSpec(locationMarker: "3️⃣", message: "expected return type in function type", fixIts: ["insert return type"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected code '() -> T)' in function"), ], fixedSource: """ diff --git a/Tests/SwiftParserTest/translated/MultilineErrorsTests.swift b/Tests/SwiftParserTest/translated/MultilineErrorsTests.swift index 412ce3d397d..4f6343968bb 100644 --- a/Tests/SwiftParserTest/translated/MultilineErrorsTests.swift +++ b/Tests/SwiftParserTest/translated/MultilineErrorsTests.swift @@ -84,10 +84,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Eleven 1️⃣Mu - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -105,10 +109,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Twelve 1️⃣\tNu - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -125,10 +133,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ \(42 1️⃣) - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -145,10 +157,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ \(42 1️⃣) - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -166,10 +182,14 @@ final class MultilineErrorsTests: XCTestCase { Foo 1️⃣\ Bar - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -188,10 +208,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Thirteen 1️⃣ Xi - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "unexpected tab in indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "unexpected tab in indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -209,10 +233,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Fourteen 1️⃣ Pi - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "unexpected tab in indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "unexpected tab in indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -230,10 +258,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Thirteen 2 1️⃣ Xi 2 - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "unexpected space in indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "unexpected space in indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -251,10 +283,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ Fourteen 2 1️⃣ Pi 2 - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "unexpected space in indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "unexpected space in indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -340,10 +376,14 @@ final class MultilineErrorsTests: XCTestCase { _ = """ 1️⃣ Hello, World! - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "unexpected space in indentation of the next 2 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "unexpected space in indentation of the next 2 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -370,12 +410,27 @@ final class MultilineErrorsTests: XCTestCase { Four B Five A Five B - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "insufficient indentation of the next 4 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected space in indentation of the next 2 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "insufficient indentation of the next 2 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "insufficient indentation of the next 4 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected space in indentation of the next 2 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "insufficient indentation of the next 2 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), ], fixedSource: #""" _ = """ @@ -403,10 +458,14 @@ final class MultilineErrorsTests: XCTestCase { 1️⃣Zero A\(1)B Zero B X - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of the next 2 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of the next 2 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" _ = """ @@ -425,11 +484,21 @@ final class MultilineErrorsTests: XCTestCase { 1️⃣Incorrect 1 Correct 2️⃣Incorrect 2 - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), ], fixedSource: #""" _ = """ @@ -444,15 +513,28 @@ final class MultilineErrorsTests: XCTestCase { func testMultilineErrors18() { assertParseWithAllNewlineEndings( ##""" - _ = "hello\(""" + _ = 1️⃣"hello\2️⃣(""" world - """1️⃣ - 2️⃣)!" + """3️⃣ + 4️⃣)!" """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ')' in string literal", fixIts: [#"insert ')'"#]), - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"extraneous code ')!"' at top level"#), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: [#"insert ')'"#] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"extraneous code ')!"' at top level"# + ), ], fixedSource: ##""" _ = "hello\(""" @@ -466,15 +548,27 @@ final class MultilineErrorsTests: XCTestCase { func testMultilineErrors19() { assertParseWithAllNewlineEndings( ##""" - _ = "h\(1️⃣ + _ = ℹ️"h\(1️⃣ """ world """2️⃣)!" """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected value and ')' in string literal", fixIts: ["insert value and ')'"]), - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"extraneous code ')!"' at top level"#), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected value and ')' in string literal", + fixIts: ["insert value and ')'"] + ), + DiagnosticSpec( + locationMarker: "1️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"extraneous code ')!"' at top level"# + ), ], fixedSource: ##""" _ = "h\(<#expression#>)" @@ -594,12 +688,20 @@ final class MultilineErrorsTests: XCTestCase { func testMultilineErrors26() { assertParseWithAllNewlineEndings( ##""" - _ = """ + _ = ℹ️""" foo1️⃣\2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "invalid escape sequence in literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "invalid escape sequence in literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), ], fixedSource: ##""" _ = """ @@ -649,14 +751,27 @@ final class MultilineErrorsTests: XCTestCase { ##""" let _ = """ foo - \ℹ️("bar1️⃣ - 2️⃣baz3️⃣ + \1️⃣(2️⃣"bar3️⃣ + 4️⃣baz5️⃣ """ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"unexpected code 'baz' in string literal"#), - DiagnosticSpec(locationMarker: "3️⃣", message: #"expected ')' in string literal"#, notes: [NoteSpec(message: "to match this opening '('")], fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "2️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"unexpected code 'baz' in string literal"# + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: #"expected ')' in string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: ##""" let _ = """ @@ -673,16 +788,29 @@ final class MultilineErrorsTests: XCTestCase { ##""" let _ = """ foo - \ℹ️("bar1️⃣ - 2️⃣baz3️⃣ + \1️⃣(2️⃣"bar3️⃣ + 4️⃣baz5️⃣ """ abc """##, substructure: Syntax(IdentifierExprSyntax(identifier: .identifier("abc"))), diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: #"unexpected code 'baz' in string literal"#), - DiagnosticSpec(locationMarker: "3️⃣", message: #"expected ')' in string literal"#, notes: [NoteSpec(message: "to match this opening '('")], fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "2️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"unexpected code 'baz' in string literal"# + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: #"expected ')' in string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: ##""" let _ = """ @@ -719,10 +847,14 @@ final class MultilineErrorsTests: XCTestCase { \( 1️⃣1 ) - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" """ @@ -741,11 +873,21 @@ final class MultilineErrorsTests: XCTestCase { + 2️⃣2 ) - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "insufficient indentation of line in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "insufficient indentation of line in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ), ], fixedSource: #""" """ @@ -766,10 +908,14 @@ final class MultilineErrorsTests: XCTestCase { + 2 ) - """ + ℹ️""" """#, diagnostics: [ - DiagnosticSpec(message: "insufficient indentation of the next 3 lines in multi-line string literal", fixIts: ["change indentation of this line to match closing delimiter"]) + DiagnosticSpec( + message: "insufficient indentation of the next 3 lines in multi-line string literal", + notes: [NoteSpec(message: "should match indentation here")], + fixIts: ["change indentation of this line to match closing delimiter"] + ) ], fixedSource: #""" """ diff --git a/Tests/SwiftParserTest/translated/MultilinePoundDiagnosticArgRdar41154797Tests.swift b/Tests/SwiftParserTest/translated/MultilinePoundDiagnosticArgRdar41154797Tests.swift index 87ddcaf84a5..0183eced16f 100644 --- a/Tests/SwiftParserTest/translated/MultilinePoundDiagnosticArgRdar41154797Tests.swift +++ b/Tests/SwiftParserTest/translated/MultilinePoundDiagnosticArgRdar41154797Tests.swift @@ -18,11 +18,21 @@ final class MultilinePoundDiagnosticArgRdar41154797Tests: XCTestCase { func testMultilinePoundDiagnosticArgRdar411547971() { assertParse( ##""" - #error("""1️⃣ + #error1️⃣(2️⃣"""3️⃣ """##, diagnostics: [ - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), - DiagnosticSpec(message: "expected ')' to end macro expansion", fixIts: ["insert ')'"]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(locationMarker: "2️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' to end macro expansion", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: ##""" #error("""""") diff --git a/Tests/SwiftParserTest/translated/ObjectLiteralsTests.swift b/Tests/SwiftParserTest/translated/ObjectLiteralsTests.swift index 72dc952b6c3..08b83885000 100644 --- a/Tests/SwiftParserTest/translated/ObjectLiteralsTests.swift +++ b/Tests/SwiftParserTest/translated/ObjectLiteralsTests.swift @@ -123,10 +123,15 @@ final class ObjectLiteralsTests: XCTestCase { func testObjectLiterals5() { assertParse( """ - let _ = [#Color(_: 1, green: 1, 2)2️⃣ + let _ = ℹ️[#Color(_: 1, green: 1, 2)2️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]) + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(message: "to match this opening '['")], + fixIts: ["insert ']'"] + ) ], fixedSource: """ let _ = [#Color(_: 1, green: 1, 2)] @@ -137,11 +142,20 @@ final class ObjectLiteralsTests: XCTestCase { func testObjectLiterals6() { assertParse( """ - let _ = [1️⃣#Color(red: 1, green: 1, blue: 1)#2️⃣3️⃣ + let _ = ℹ️[1️⃣#Color(red: 1, green: 1, blue: 1)#2️⃣3️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "2️⃣", message: "expected identifier in macro expansion", fixIts: ["insert identifier"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected identifier in macro expansion", + fixIts: ["insert identifier"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), ], fixedSource: """ let _ = [#Color(red: 1, green: 1, blue: 1)#<#identifier#>] diff --git a/Tests/SwiftParserTest/translated/OriginalDefinedInAttrTests.swift b/Tests/SwiftParserTest/translated/OriginalDefinedInAttrTests.swift index aa7b41489fd..2d471a6b8d4 100644 --- a/Tests/SwiftParserTest/translated/OriginalDefinedInAttrTests.swift +++ b/Tests/SwiftParserTest/translated/OriginalDefinedInAttrTests.swift @@ -115,12 +115,19 @@ final class OriginalDefinedInAttrTests: XCTestCase { func testOriginalDefinedInAttr6() { assertParse( #""" - @_originallyDefinedIn(module: "foo",1️⃣ + @_originallyDefinedInℹ️(module: "foo",1️⃣ public class ToplevelClass3 {} """#, diagnostics: [ - DiagnosticSpec(message: "expected version restriction in version", fixIts: ["insert version restriction"]), - DiagnosticSpec(message: "expected ')' to end attribute", fixIts: ["insert ')'"]), + DiagnosticSpec( + message: "expected version restriction in version", + fixIts: ["insert version restriction"] + ), + DiagnosticSpec( + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), ], fixedSource: #""" @_originallyDefinedIn(module: "foo", <#identifier#>) diff --git a/Tests/SwiftParserTest/translated/RecoveryTests.swift b/Tests/SwiftParserTest/translated/RecoveryTests.swift index 05163a32947..05c747f4a3f 100644 --- a/Tests/SwiftParserTest/translated/RecoveryTests.swift +++ b/Tests/SwiftParserTest/translated/RecoveryTests.swift @@ -47,17 +47,36 @@ final class RecoveryTests: XCTestCase { assertParse( """ func useContainer() -> () { - var a : Container] >4️⃣, b : Int + var a : Containerℹ️] >4️⃣, b : Int b = 5 // no-warning a.exists() } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '>' to end generic argument clause", fixIts: ["insert '>'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "consecutive statements on a line must be separated by ';'", fixIts: ["insert ';'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected code 'this greater: >' in subscript"), - DiagnosticSpec(locationMarker: "4️⃣", message: "expected expression after operator", fixIts: ["insert expression"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code in function"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "consecutive statements on a line must be separated by ';'", + fixIts: ["insert ';'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "unexpected code 'this greater: >' in subscript" + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected expression after operator", + fixIts: ["insert expression"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code in function" + ), ], fixedSource: """ func useContainer() -> () { @@ -1063,12 +1082,16 @@ final class RecoveryTests: XCTestCase { assertParse( """ struct ErrorTypeInVarDecl3 { - var v1 : Int< 1️⃣ + var v1 : Intℹ️< 1️⃣ var v2 : Int } """, diagnostics: [ - DiagnosticSpec(message: "expected '>' to end generic argument clause", fixIts: ["insert '>'"]) + DiagnosticSpec( + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ) ], fixedSource: """ struct ErrorTypeInVarDecl3 { @@ -1083,12 +1106,16 @@ final class RecoveryTests: XCTestCase { assertParse( """ struct ErrorTypeInVarDecl4 { - var v1 : Int<1️⃣, + var v1 : Intℹ️<1️⃣, var v2 : Int } """, diagnostics: [ - DiagnosticSpec(message: "expected '>' to end generic argument clause", fixIts: ["insert '>'"]) + DiagnosticSpec( + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ) ], fixedSource: """ struct ErrorTypeInVarDecl4 { @@ -1103,12 +1130,16 @@ final class RecoveryTests: XCTestCase { assertParse( """ struct ErrorTypeInVarDecl5 { - var v1 : Int' to end generic argument clause", fixIts: ["insert '>'"]) + DiagnosticSpec( + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ) ], fixedSource: """ struct ErrorTypeInVarDecl5 { @@ -1151,13 +1182,20 @@ final class RecoveryTests: XCTestCase { assertParse( """ struct ErrorTypeInVarDecl7 { - var v1 : Int' to end generic argument clause", fixIts: ["insert '>'"]), + DiagnosticSpec( + message: "expected type in generic argument", + fixIts: ["insert type"] + ), + DiagnosticSpec( + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), ], fixedSource: """ struct ErrorTypeInVarDecl7 { @@ -1245,11 +1283,18 @@ final class RecoveryTests: XCTestCase { func testRecovery87() { assertParse( """ - struct ErrorGenericParameterList1<1️⃣ + struct ErrorGenericParameterList1ℹ️<1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "expected member block in struct", + fixIts: ["insert member block"] + ), ], fixedSource: """ struct ErrorGenericParameterList1< > { @@ -1261,12 +1306,22 @@ final class RecoveryTests: XCTestCase { func testRecovery87b() { assertParse( """ - struct ErrorGenericParameterList1' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]), + DiagnosticSpec( + message: "expected name in generic parameter", + fixIts: ["insert name"] + ), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "expected member block in struct", + fixIts: ["insert member block"] + ), ], fixedSource: """ struct ErrorGenericParameterList1> { @@ -1278,11 +1333,18 @@ final class RecoveryTests: XCTestCase { func testRecovery88() { assertParse( """ - struct ErrorGenericParameterList2' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "expected member block in struct", + fixIts: ["insert member block"] + ), ], fixedSource: """ struct ErrorGenericParameterList2 { @@ -1294,12 +1356,22 @@ final class RecoveryTests: XCTestCase { func testRecovery89() { assertParse( """ - struct ErrorGenericParameterList3' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(message: "expected member block in struct", fixIts: ["insert member block"]), + DiagnosticSpec( + message: "expected generic parameter in generic parameter clause", + fixIts: ["insert generic parameter"] + ), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "expected member block in struct", + fixIts: ["insert member block"] + ), ], fixedSource: """ struct ErrorGenericParameterList3> { @@ -1312,12 +1384,16 @@ final class RecoveryTests: XCTestCase { // Note: Don't move braces to a different line here. assertParse( """ - struct ErrorGenericParameterList4<1️⃣ + struct ErrorGenericParameterList4ℹ️<1️⃣ { } """, diagnostics: [ - DiagnosticSpec(message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]) + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ) ], fixedSource: """ struct ErrorGenericParameterList4< > @@ -1331,12 +1407,16 @@ final class RecoveryTests: XCTestCase { // Note: Don't move braces to a different line here. assertParse( """ - struct ErrorGenericParameterList5' to end generic parameter clause", fixIts: ["insert '>'"]) + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ) ], fixedSource: """ struct ErrorGenericParameterList5 @@ -1350,13 +1430,20 @@ final class RecoveryTests: XCTestCase { // Note: Don't move braces to a different line here. assertParse( """ - struct ErrorGenericParameterList6' to end generic parameter clause", fixIts: ["insert '>'"]), + DiagnosticSpec( + message: "expected generic parameter in generic parameter clause", + fixIts: ["insert generic parameter"] + ), + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), ], fixedSource: """ struct ErrorGenericParameterList6> @@ -1412,10 +1499,14 @@ final class RecoveryTests: XCTestCase { func testRecovery98b() { assertParse( """ - let a2: Set + let a2: Setℹ️ """, diagnostics: [ - DiagnosticSpec(message: "expected '>' to end generic argument clause", fixIts: ["insert '>'"]), + DiagnosticSpec( + message: "expected '>' to end generic argument clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), DiagnosticSpec(message: "extraneous code ']>' at top level"), ], fixedSource: """ @@ -1491,20 +1582,37 @@ final class RecoveryTests: XCTestCase { func testRecovery100() { assertParse( """ - struct ErrorInFunctionSignatureResultArrayType1 { - func foo() -> Int1️⃣[ { + struct ErrorInFunctionSignatureResultArrayType1 1️⃣{ + func foo() -> Int2️⃣[ { return [0] - } 2️⃣ - func bar() -> Int3️⃣] { + } 3️⃣ + func bar() -> Int4️⃣] { return [0] } - 4️⃣} + 5️⃣} """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected ']' in type; did you mean to write an array type?", fixIts: ["insert '['"]), - DiagnosticSpec(locationMarker: "4️⃣", message: "extraneous brace at top level"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected ']' in type; did you mean to write an array type?", + fixIts: ["insert '['"] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "extraneous brace at top level" + ), ], fixedSource: """ struct ErrorInFunctionSignatureResultArrayType1 { @@ -1523,18 +1631,31 @@ final class RecoveryTests: XCTestCase { func testRecovery101() { assertParse( """ - struct ErrorInFunctionSignatureResultArrayType2 { - func foo() -> Int1️⃣[0 { + struct ErrorInFunctionSignatureResultArrayType2 1️⃣{ + func foo() -> Int2️⃣[0 { return [0] - }2️⃣ - 3️⃣} + }3️⃣ + 4️⃣} """, diagnostics: [ // TODO: Old parser expected error on line 2: expected ']' in array type // TODO: Old parser expected note on line 2: to match this opening '[' - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous brace at top level"), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "extraneous brace at top level" + ), ], fixedSource: """ struct ErrorInFunctionSignatureResultArrayType2 { @@ -1595,14 +1716,22 @@ final class RecoveryTests: XCTestCase { func testRecovery105() { assertParse( """ - struct ErrorInFunctionSignatureResultArrayType11 { + struct ErrorInFunctionSignatureResultArrayType11 ℹ️{ func foo() -> Int1️⃣[(a){a++}] { } 2️⃣} """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "extraneous brace at top level"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "extraneous brace at top level" + ), ], fixedSource: """ struct ErrorInFunctionSignatureResultArrayType11 { @@ -2060,13 +2189,25 @@ final class RecoveryTests: XCTestCase { """ switch esp { case let (jeb): - class Ceac<1️⃣}2️⃣> {} + class Ceacℹ️<1️⃣}2️⃣> {} } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '{' in class", fixIts: ["insert '{'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code '> {}' in 'switch' statement"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '{' in class", + fixIts: ["insert '{'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "unexpected code '> {}' in 'switch' statement" + ), ], fixedSource: """ switch esp { @@ -2082,17 +2223,38 @@ final class RecoveryTests: XCTestCase { assertParse( """ #if true - struct Foo19605164 { - func a(s: S1️⃣[{{g2️⃣) -> Int {} - }}3️⃣} + struct Foo19605164 1️⃣{ + func a2️⃣(s: S3️⃣[{{g4️⃣) -> Int {} + }}5️⃣} #endif """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code ') -> Int {}' in closure"), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected ']' to end array", fixIts: ["insert ']'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected brace in conditional compilation block"), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code ') -> Int {}' in closure" + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "expected ']' to end array", + notes: [NoteSpec(locationMarker: "3️⃣", message: "to match this opening '['")], + fixIts: ["insert ']'"] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "unexpected brace in conditional compilation block" + ), ], fixedSource: """ #if true @@ -2109,16 +2271,33 @@ final class RecoveryTests: XCTestCase { // rdar://19605567 assertParse( """ - func F() { init<1️⃣( 2️⃣} 3️⃣)} + func F() { init1️⃣<2️⃣( 3️⃣} 4️⃣)} struct InitializerWithName { - init 4️⃣x() {}5️⃣ + init 5️⃣x() {} } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '>' to end generic parameter clause", fixIts: ["insert '>'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end parameter clause", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: "unexpected code ')}' before struct"), - DiagnosticSpec(locationMarker: "4️⃣", message: "initializers cannot have a name", fixIts: ["remove 'x'"]), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '>' to end generic parameter clause", + notes: [NoteSpec(locationMarker: "1️⃣", message: "to match this opening '<'")], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' to end parameter clause", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "unexpected code ')}' before struct" + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "initializers cannot have a name", + fixIts: ["remove 'x'"] + ), ], fixedSource: """ func F() { init< >()} )} @@ -2538,11 +2717,15 @@ final class RecoveryTests: XCTestCase { let a = s.startIndex.. String { @@ -2635,13 +2818,21 @@ final class RecoveryTests: XCTestCase { func testRecovery179() { assertParse( """ - func testSkipUnbalancedParen() {1️⃣ + func testSkipUnbalancedParen() ℹ️{1️⃣ 2️⃣?( } """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '}' to end function", fixIts: ["insert '}'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "extraneous code at top level"), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "extraneous code at top level" + ), ], fixedSource: """ func testSkipUnbalancedParen() { @@ -2655,14 +2846,27 @@ final class RecoveryTests: XCTestCase { func testRecovery180() { assertParse( """ - func testSkipToFindOpenBrace1() { + func testSkipToFindOpenBrace1() ℹ️{ do { if case 1️⃣} }2️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected expression, '=', and expression in pattern matching", fixIts: ["insert expression, '=', and expression"]), - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '{' in 'if' statement", fixIts: ["insert '{'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end function", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected expression, '=', and expression in pattern matching", + fixIts: ["insert expression, '=', and expression"] + ), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '{' in 'if' statement", + fixIts: ["insert '{'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: """ func testSkipToFindOpenBrace1() { @@ -2676,13 +2880,21 @@ final class RecoveryTests: XCTestCase { func testRecovery181() { assertParse( """ - func testSkipToFindOpenBrace2() { + func testSkipToFindOpenBrace2() ℹ️{ do { if true {} else 1️⃣false } }2️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '{' or 'if' after 'else'"), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end function", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '{' or 'if' after 'else'" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end function", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: """ func testSkipToFindOpenBrace2() { diff --git a/Tests/SwiftParserTest/translated/RegexParseErrorTests.swift b/Tests/SwiftParserTest/translated/RegexParseErrorTests.swift index 0cf27fe4543..63478273b06 100644 --- a/Tests/SwiftParserTest/translated/RegexParseErrorTests.swift +++ b/Tests/SwiftParserTest/translated/RegexParseErrorTests.swift @@ -50,10 +50,14 @@ final class RegexParseErrorTests: XCTestCase { func testRegexParseError6() { assertParse( #""" - _ = #/\\/''/1️⃣ + _ = ℹ️#/\\/''/1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: "expected '#' to end regex literal", fixIts: ["insert '#'"]) + DiagnosticSpec( + message: "expected '#' to end regex literal", + notes: [NoteSpec(message: "to match this opening '#'")], + fixIts: ["insert '#'"] + ) ], fixedSource: #""" _ = #/\\/''/# @@ -78,10 +82,14 @@ final class RegexParseErrorTests: XCTestCase { func testRegexParseError8() { assertParse( """ - _ = #//1️⃣ + _ = ℹ️#//1️⃣ """, diagnostics: [ - DiagnosticSpec(message: "expected '#' to end regex literal", fixIts: ["insert '#'"]) + DiagnosticSpec( + message: "expected '#' to end regex literal", + notes: [NoteSpec(message: "to match this opening '#'")], + fixIts: ["insert '#'"] + ) ], fixedSource: """ _ = #//# diff --git a/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift b/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift index 362bcd4d7ec..25e8986da35 100644 --- a/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift +++ b/Tests/SwiftParserTest/translated/StringLiteralEofTests.swift @@ -19,11 +19,18 @@ final class StringLiteralEofTests: XCTestCase { assertParse( ##""" // NOTE: DO NOT add a newline at EOF. - _ = "foo\(1️⃣ + _ = ℹ️"foo\(1️⃣ """##, diagnostics: [ - DiagnosticSpec(message: "expected value and ')' in string literal", fixIts: ["insert value and ')'"]), - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + message: "expected value and ')' in string literal", + fixIts: ["insert value and ')'"] + ), + DiagnosticSpec( + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" // NOTE: DO NOT add a newline at EOF. @@ -64,11 +71,19 @@ final class StringLiteralEofTests: XCTestCase { func testStringLiteralEof3() { assertParse( ##""" - _ = "foo 1️⃣\2️⃣ + _ = ℹ️"foo 1️⃣\2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "invalid escape sequence in literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "invalid escape sequence in literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" _ = "foo \" @@ -80,11 +95,19 @@ final class StringLiteralEofTests: XCTestCase { assertParse( ##""" // NOTE: DO NOT add a newline at EOF. - _ = "foo 1️⃣\2️⃣ + _ = ℹ️"foo 1️⃣\2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "invalid escape sequence in literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "invalid escape sequence in literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" // NOTE: DO NOT add a newline at EOF. @@ -97,11 +120,15 @@ final class StringLiteralEofTests: XCTestCase { assertParse( #""" // NOTE: DO NOT add a newline at EOF. - _ = """ + _ = ℹ️""" foo1️⃣ """#, diagnostics: [ - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]) + DiagnosticSpec( + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ) ], fixedSource: #""" // NOTE: DO NOT add a newline at EOF. @@ -115,13 +142,20 @@ final class StringLiteralEofTests: XCTestCase { // NOTE: DO NOT add a newline at EOF. assertParse( ##""" - _ = """ + _ = ℹ️""" foo \(1️⃣ """##, diagnostics: [ - DiagnosticSpec(message: "expected value and ')' in string literal", fixIts: ["insert value and ')'"]), - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), + DiagnosticSpec( + message: "expected value and ')' in string literal", + fixIts: ["insert value and ')'"] + ), + DiagnosticSpec( + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), ], fixedSource: ##""" _ = """ @@ -136,14 +170,29 @@ final class StringLiteralEofTests: XCTestCase { // NOTE: DO NOT add a newline at EOF. assertParse( ##""" - _ = """ + _ = 1️⃣""" foo - \("bar1️⃣ + \2️⃣(3️⃣"bar4️⃣ """##, diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), ], fixedSource: ##""" _ = """ @@ -156,15 +205,33 @@ final class StringLiteralEofTests: XCTestCase { func testStringLiteralEof8() { assertParse( ##""" - _ = """ - \("bar1️⃣ - 2️⃣baz3️⃣ + _ = 1️⃣""" + \2️⃣(3️⃣"bar4️⃣ + 5️⃣baz6️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(locationMarker: "2️⃣", message: "unexpected code 'baz' in string literal"), - DiagnosticSpec(locationMarker: "3️⃣", message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(locationMarker: "3️⃣", message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "5️⃣", + message: "unexpected code 'baz' in string literal" + ), + DiagnosticSpec( + locationMarker: "6️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "6️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), ], fixedSource: ##""" _ = """ diff --git a/Tests/SwiftParserTest/translated/SubscriptingTests.swift b/Tests/SwiftParserTest/translated/SubscriptingTests.swift index 161c185f028..a0f09694feb 100644 --- a/Tests/SwiftParserTest/translated/SubscriptingTests.swift +++ b/Tests/SwiftParserTest/translated/SubscriptingTests.swift @@ -427,7 +427,7 @@ final class SubscriptingTests: XCTestCase { func testSubscripting21() { assertParse( """ - struct A8 { + struct A8 ℹ️{ subscript(i : Int) -> Int1️⃣ get { return stored @@ -438,8 +438,17 @@ final class SubscriptingTests: XCTestCase { }2️⃣ """, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "expected '{' in subscript", fixIts: ["insert '{'"]), - DiagnosticSpec(locationMarker: "2️⃣", message: "expected '}' to end struct", fixIts: ["insert '}'"]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "expected '{' in subscript", + fixIts: ["insert '{'"] + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: "expected '}' to end struct", + notes: [NoteSpec(message: "to match this opening '{'")], + fixIts: ["insert '}'"] + ), ], fixedSource: """ struct A8 { diff --git a/Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift b/Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift index 9630dbe6a64..9a8868c6002 100644 --- a/Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift +++ b/Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift @@ -26,10 +26,14 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation2() { assertParse( ##""" - _ = "mid == \(pete1️⃣" + _ = "mid == \ℹ️(pete1️⃣" """##, diagnostics: [ - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' in string literal", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: ##""" _ = "mid == \(pete)" @@ -40,12 +44,27 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation3() { assertParse( ##""" - let theGoat = "kanye \("1️⃣ + let theGoat = 1️⃣"kanye \2️⃣(3️⃣"4️⃣ """##, diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" let theGoat = "kanye \("")" @@ -56,24 +75,33 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation4() { assertParse( ##""" - let equation1 = "2 + 2 = \(2 + 21️⃣" + let equation1 = "2 + 2 = \ℹ️(2 + 21️⃣" """##, diagnostics: [ - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' in string literal", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: ##""" let equation1 = "2 + 2 = \(2 + 2)" """## + ) } func testUnclosedStringInterpolation5() { assertParse( ##""" - let s = "\(x1️⃣"; print(x) + let s = "\ℹ️(x1️⃣"; print(x) """##, diagnostics: [ - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]) + DiagnosticSpec( + message: "expected ')' in string literal", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ) ], fixedSource: ##""" let s = "\(x)"; print(x) @@ -84,11 +112,19 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation6() { assertParse( ##""" - let zzz = "\(x1️⃣; print(x)2️⃣ + let zzz = ℹ️"\(x1️⃣; print(x)2️⃣ """##, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '; print(x' in string literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code '; print(x' in string literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" let zzz = "\(x; print(x)" @@ -99,11 +135,21 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation7() { assertParse( ##""" - let goatedAlbum = "The Life Of \("Pablo"1️⃣ + let goatedAlbum = 1️⃣"The Life Of \2️⃣("Pablo"3️⃣ """##, diagnostics: [ - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "3️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "3️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: ##""" let goatedAlbum = "The Life Of \("Pablo")" @@ -114,14 +160,29 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnclosedStringInterpolation8() { assertParse( ##""" - _ = """ - \( - """1️⃣ + _ = 1️⃣""" + \2️⃣( + 3️⃣"""4️⃣ """##, diagnostics: [ - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"""' to end string literal"#, fixIts: [#"insert '"""'"#]), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"""' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"""'"#)], + fixIts: [#"insert '"""'"#] + ), ], fixedSource: ##""" _ = """ @@ -134,11 +195,19 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testSkipUnexpectedOpeningParensInStringLiteral() { assertParse( #""" - "\(e 1️⃣H()r2️⃣ + ℹ️"\(e 1️⃣H()r2️⃣ """#, diagnostics: [ - DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'H(' in string literal"), - DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "1️⃣", + message: "unexpected code 'H(' in string literal" + ), + DiagnosticSpec( + locationMarker: "2️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "\(e H()r" @@ -149,12 +218,27 @@ final class UnclosedStringInterpolationTests: XCTestCase { func testUnterminatedStringLiteralInInterpolation() { assertParse( #""" - "\("1️⃣ + 1️⃣"\2️⃣(3️⃣"4️⃣ """#, diagnostics: [ - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), - DiagnosticSpec(message: "expected ')' in string literal", fixIts: ["insert ')'"]), - DiagnosticSpec(message: #"expected '"' to end string literal"#, fixIts: [#"insert '"'"#]), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "3️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: "expected ')' in string literal", + notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + DiagnosticSpec( + locationMarker: "4️⃣", + message: #"expected '"' to end string literal"#, + notes: [NoteSpec(locationMarker: "1️⃣", message: #"to match this opening '"'"#)], + fixIts: [#"insert '"'"#] + ), ], fixedSource: #""" "\("")"