Files
swift-mirror/test/diagnostics/pretty-printed-diagnostics.swift
Owen Voorhees d220ac80f3 [Diag-Experimental-Formatting] Better rendering of multi-line fix-its
- Fix an off-by-one error when a fix-it continues onto a newline
- Don't print multi-line insertions inline due to poor UX
- When printing multi-line fix-its out of line attached to a message,
  replace newlines with the carriage return emoji
- Don't underline a line's leading whitespace unless it's part of an insertion
2020-03-04 11:57:39 -08:00

215 lines
7.7 KiB
Swift

// RUN: not %target-swift-frontend -enable-experimental-diagnostic-formatting -typecheck %s 2>&1 | %FileCheck %s
1 + 2
func foo(a: Int, b: Int) {
a + b
}
foo(b: 1, a: 2)
func baz() {
bar(a: "hello, world!")
}
struct Foo {
var x: Int
var x: Int
}
func bar(a: Int) {}
func bar(a: Float) {}
func bazz() throws {
}
bazz()
struct A {}
extension A {
let x: Int = { 42 }
}
let abc = "👍
let x = {
let y = 1
return y
}
struct B: Decodable {
let a: Foo
}
// The line below is indented with tabs, not spaces.
foo(b: 1, a: 2)
let 👍👍👍 = {
let y = 1
return y
}
// Multi-line fix-its
foo(b: 1,
a: 2)
foo(b:
1,
a:
2)
foo(b:
1,
a: 2)
// Test fallback for non-ASCII characters.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:11
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | let abc = "👍
// CHECK: | --> error: unterminated string literal
// CHECK: [[#LINE+1]] |
// Test underlining.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:3
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | 1 + 2
// CHECK: | ~ ~
// CHECK: | ^ warning: result of operator '+' is unused
// CHECK: [[#LINE+1]] |
// Test inline fix-it rendering.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:11
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | foo(a: 2, b: 1, a: 2)
// CHECK: | ++++++~~~~------
// CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ', a: 2' and insert 'a: 2, ']
// CHECK: [[#LINE+1]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:7
// CHECK: [[#LINE-2]] | struct Foo {
// CHECK: [[#LINE-1]] | var x: Int
// CHECK: | ^ note: 'x' previously declared here
// CHECK: [[#LINE]] | var x: Int
// CHECK: | ^ error: invalid redeclaration of 'x'
// CHECK: [[#LINE+1]] | }
// Test out-of-line fix-its on notes.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:1
// CHECK: [[#LINE-1]] | }
// CHECK: [[#LINE]] | bazz()
// CHECK: | ~~~~~~
// CHECK: | ^ error: call can throw but is not marked with 'try'
// CHECK: | ^ note: did you mean to use 'try'? [insert 'try ']
// CHECK: | ^ note: did you mean to handle error as optional value? [insert 'try? ']
// CHECK: | ^ note: did you mean to disable error propagation? [insert 'try! ']
// CHECK: [[#LINE+1]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:7
// CHECK: [[#LINE-1]] | extension A {
// CHECK: [[#LINE]] | let x: Int = { 42 }
// CHECK: | ^ error: extensions must not contain stored properties
// CHECK: [[#LINE+1]] | }
// Test complex out-of-line fix-its.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:16
// CHECK: [[#LINE-1]] | extension A {
// CHECK: [[#LINE]] | let x: Int = { 42 }()
// CHECK: | ~~~~~~++
// CHECK: | ^ error: function produces expected type 'Int'; did you mean to call it with '()'?
// CHECK: | ^ note: Remove '=' to make 'x' a computed property [remove '= ' and replace 'let' with 'var']
// CHECK: [[#LINE+1]] | }
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:9
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | let x = { () -> Result in
// CHECK: | +++++++++++++++++
// CHECK: | ^ error: unable to infer complex closure return type; add explicit type to disambiguate
// CHECK: [[#LINE+1]] | let y = 1
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:8
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | struct B: Decodable {
// CHECK: | ^ error: type 'B' does not conform to protocol 'Decodable'
// CHECK: [[#LINE+1]] | let a: Foo
// CHECK: | ^ note: cannot automatically synthesize 'Decodable' because 'Foo' does not conform to 'Decodable'
// CHECK: [[#LINE+2]] | }
// CHECK: Swift.Decodable:2:5
// CHECK: 1 | public protocol Decodable {
// CHECK: 2 | init(from decoder: Decoder) throws
// CHECK: | ^ note: protocol requires initializer 'init(from:)' with type 'Decodable'
// CHECK: 3 | }
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:14
// CHECK: [[#LINE-1]] | // The line below is indented with tabs, not spaces.
// CHECK: [[#LINE]] | foo(a: 2, b: 1, a: 2)
// CHECK: | ++++++~~~~------
// CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ', a: 2' and insert 'a: 2, ']
// CHECK: [[#LINE+1]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:20
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | let 👍👍👍 = {
// CHECK: | --> error: unable to infer complex closure return type; add explicit type to disambiguate [insert ' () -> <#Result#> in ']
// CHECK: [[#LINE+1]] | let y = 1
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5
// CHECK: [[#LINE-2]] | // Multi-line fix-its
// CHECK: [[#LINE-1]] | foo(a: 2, b: 1,
// CHECK: | ++++++~~~~-
// CHECK: [[#LINE]] | a: 2)
// CHECK: | ----
// CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ',\n a: 2' and insert 'a: 2, ']
// CHECK: [[#LINE+1]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5
// CHECK: [[#LINE-3]] |
// CHECK: [[#LINE-2]] | foo(b:
// CHECK: | ~~
// CHECK: [[#LINE-1]] | 1,
// CHECK: | ~-
// CHECK: [[#LINE]] | a:
// CHECK: | --
// CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ',\n a:\n 2' and insert 'a:\n 2, ']
// CHECK: [[#LINE+1]] | 2)
// CHECK: | -
// CHECK: [[#LINE+2]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5
// CHECK: [[#LINE-3]] |
// CHECK: [[#LINE-2]] | foo(a: 2, b:
// CHECK: | ++++++~~
// CHECK: [[#LINE-1]] | 1,
// CHECK: | ~-
// CHECK: [[#LINE]] | a: 2)
// CHECK: | ----
// CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ',\n a: 2' and insert 'a: 2, ']
// CHECK: [[#LINE+1]] |
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5
// CHECK: [[#LINE-1]] | func foo(a: Int, b: Int) {
// CHECK: [[#LINE]] | a + b
// CHECK: | ~ ~
// CHECK: | ^ warning: result of operator '+' is unused
// CHECK: [[#LINE+1]] | }
// Test snippet truncation.
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:3
// CHECK: [[#LINE-1]] | func baz() {
// CHECK: [[#LINE]] | bar(a: "hello, world!")
// CHECK: | ^ error: no exact matches in call to global function 'bar'
// CHECK: [[#LINE+1]] | }
// CHECK: ...
// CHECK: [[#LINE:]] |
// CHECK: [[#LINE+1]] | func bar(a: Int) {}
// CHECK: | ^ note: candidate expects value of type 'Int' for parameter #1
// CHECK: [[#LINE+2]] | func bar(a: Float) {}
// CHECK: | ^ note: candidate expects value of type 'Float' for parameter #1
// CHECK: [[#LINE+3]] |