Skip to content

DiagnosticVerifier: Allow specifying locations vs. ranges in fix-it verifications #41484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions lib/Frontend/DiagnosticVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,14 @@ DiagnosticVerifier::renderFixits(ArrayRef<CapturedFixItInfo> ActualFixIts,
OS << ActualRange.StartLine << ':';
OS << ActualRange.StartCol;

OS << '-';
const bool isMultiline = ActualRange.StartLine != ActualRange.EndLine;
if (isMultiline || ActualRange.StartCol != ActualRange.EndCol) {
OS << '-';

if (ActualRange.EndLine != ActualRange.StartLine)
OS << ActualRange.EndLine << ':';
OS << ActualRange.EndCol;
if (isMultiline)
OS << ActualRange.EndLine << ':';
OS << ActualRange.EndCol;
}

OS << '=';

Expand All @@ -339,12 +342,15 @@ DiagnosticVerifier::renderFixits(ArrayRef<CapturedFixItInfo> ActualFixIts,
return OS.str();
}

/// Parse the introductory line-column range of an expected fix-it by consuming
/// the given input string. The range format is \c ([+-]?N:)?N-([+-]?N:)?N
/// where \c 'N' is \c [0-9]+.
/// Parse the introductory line-column location or replacement range of an
/// expected fix-it by consuming the given input string. The location format is
/// \c ([+-]?N:)?N where \c N is \c [0-9]+, and the range format is two
/// locations separated with \c '-'.
///
/// \param DiagnosticLineNo The line number of the associated expected
/// diagnostic; used to turn line offsets into line numbers.
///
/// \returns A line-column range, or \c None if an error ocurred.
static Optional<LineColumnRange> parseExpectedFixItRange(
StringRef &Str, unsigned DiagnosticLineNo,
llvm::function_ref<void(const char *, const Twine &)> diagnoseError) {
Expand Down Expand Up @@ -429,11 +435,19 @@ static Optional<LineColumnRange> parseExpectedFixItRange(
return None;
}

// If this is a location, fill in the end values and we're done.
if (!Str.empty() && Str.front() == '=') {
Range.EndLine = Range.StartLine;
Range.EndCol = Range.StartCol;

return Range;
}

if (!Str.empty() && Str.front() == '-') {
Str = Str.drop_front();
} else {
diagnoseError(Str.data(),
"expected '-' range separator in fix-it verification");
diagnoseError(Str.data(), "expected '-' range separator or '=' after "
"location in fix-it verification");
return None;
}

Expand Down
2 changes: 1 addition & 1 deletion test/FixCode/verify-fixits.swift.result
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
func f1() {
guard true { return } // expected-error {{expected 'else' after 'guard' condition}}

guard true { return } // expected-error {{expected 'else' after 'guard' condition}} {{14-14=else }} {{none}}
guard true { return } // expected-error {{expected 'else' after 'guard' condition}} {{14=else }} {{none}}
}

func labeledFunc(aa: Int, bb: Int) {}
Expand Down
44 changes: 36 additions & 8 deletions test/Frontend/verify-fixits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func test0Fixits() {
// CHECK: [[@LINE+1]]:81: error: expected line offset after leading '+' or '-' in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{-}}

// CHECK: [[@LINE+1]]:81: error: expected '-' range separator in fix-it verification
// CHECK: [[@LINE+1]]:81: error: expected '-' range separator or '=' after location in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1}}

// CHECK: [[@LINE+1]]:82: error: expected colon-separated column number after line offset in fix-it verification
Expand All @@ -33,16 +33,19 @@ func test0Fixits() {
// CHECK: [[@LINE+1]]:82: error: expected colon-separated column number after line offset in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{+1}}

// CHECK: [[@LINE+1]]:82: error: expected colon-separated column number after line offset in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{-1=}}

// CHECK: [[@LINE+1]]:82: error: expected column number after ':' in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1:}}

// CHECK: [[@LINE+1]]:83: error: expected column number after ':' in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{+1:}}

// CHECK: [[@LINE+1]]:83: error: expected '-' range separator in fix-it verification
// CHECK: [[@LINE+1]]:83: error: expected '-' range separator or '=' after location in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1:1}}

// CHECK: [[@LINE+1]]:84: error: expected '-' range separator in fix-it verification
// CHECK: [[@LINE+1]]:84: error: expected '-' range separator or '=' after location in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{-1:1}}

// CHECK: [[@LINE+1]]:83: error: expected column number after ':' in fix-it verification
Expand Down Expand Up @@ -93,6 +96,15 @@ func test0Fixits() {
// CHECK: [[@LINE+1]]:89: error: expected '=' after range in fix-it verification
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{+1:1--1:1}}

// CHECK: [[@LINE+1]]:78: error: expected fix-it not seen
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1=a}}

// CHECK: [[@LINE+1]]:78: error: expected fix-it not seen
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1:1=a}}

// CHECK: [[@LINE+1]]:78: error: expected fix-it not seen
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{-1:1=a}}

// CHECK: [[@LINE+1]]:78: error: expected fix-it not seen
undefinedFunc() // expected-error {{cannot find 'undefinedFunc' in scope}} {{1-1=}}

Expand Down Expand Up @@ -197,22 +209,22 @@ func test1Fixits() {
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15-18=xx}} {{15-18=aa}} {{none}}

// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{200:15-200:18=aa}}
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{212:15-212:18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{202:15-18=aa}}
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{214:15-18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15-204:18=aa}}
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15-216:18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{-0:15-+0:18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15--0:18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {+0:15-210:18=aa}}
labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{+0:15-222:18=aa}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aa: 0, // expected-error {{incorrect argument label in call (have 'aa:bbx:', expected 'aa:bb:')}} {{+1:15-+1:18=bb}}
bbx: 1)
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
labeledFunc(aa: 0, // expected-error {{incorrect argument label in call (have 'aa:bbx:', expected 'aa:bb:')}} {{216:15-+1:18=bb}}
labeledFunc(aa: 0, // expected-error {{incorrect argument label in call (have 'aa:bbx:', expected 'aa:bb:')}} {{228:15-+1:18=bb}}
bbx: 1)

// CHECK: [[@LINE+1]]:121: error: expected fix-it not seen; actual fix-it seen: {{{{}}15-18=aa}}
Expand Down Expand Up @@ -249,3 +261,19 @@ func test2Fixits() {
// CHECK: [[@LINE+1]]:137: error: expected fix-it not seen; actual fix-its seen: {{{{}}15-18=aa}} {{{{}}23-26=bb}}
labeledFunc(aax: 0, bbx: 1) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{15-18=aa}} {{23-26=xx}} {{none}}
}

protocol P {
associatedtype A
}
func testFixitWithLocation(_: inout Bool) {
var bool = true
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
testFixitWithLocation(bool) // expected-error {{passing value of type 'Bool' to an inout parameter requires explicit '&'}} {{25=&}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
testFixitWithLocation(bool) // expected-error {{passing value of type 'Bool' to an inout parameter requires explicit '&'}} {{+0:25=&}}
// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error:
testFixitWithLocation(bool) // expected-error {{passing value of type 'Bool' to an inout parameter requires explicit '&'}} {{25-25=&}}

// CHECK: [[@LINE+1]]:126: error: expected fix-it not seen; actual fix-it seen: {{{{}}25=&}}
testFixitWithLocation(bool) // expected-error {{passing value of type 'Bool' to an inout parameter requires explicit '&'}} {{24-24=&}}
}
10 changes: 5 additions & 5 deletions test/Generics/associated_type_where_clause_hints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ protocol P2 : P1 {
// A redeclaration of an associated type that adds type/layout requirements
// should be written via a where clause.
protocol P3a : P1 {
associatedtype A: P0, P0b // expected-warning{{redeclaration of associated type 'A' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{-1:18--1:18= where A: P0, A: P0b}}{{28:3-28:29=}}
associatedtype A2: P0, P0b where A2.A == Never, A2: P1 // expected-warning{{redeclaration of associated type 'A2' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A2: P0, A2: P0b, A2.A == Never, A2 : P1}}{{3-58=}}
associatedtype A3 where A3: P0 // expected-warning{{redeclaration of associated type 'A3' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A3 : P0}}{{3-34=}}
associatedtype A: P0, P0b // expected-warning{{redeclaration of associated type 'A' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{-1:18= where A: P0, A: P0b}}{{28:3-28:29=}}
associatedtype A2: P0, P0b where A2.A == Never, A2: P1 // expected-warning{{redeclaration of associated type 'A2' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18= where A2: P0, A2: P0b, A2.A == Never, A2 : P1}}{{3-58=}}
associatedtype A3 where A3: P0 // expected-warning{{redeclaration of associated type 'A3' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18= where A3 : P0}}{{3-34=}}

// expected-warning@+1 {{redeclaration of associated type 'A4' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{27:18-27:18= where A4: P0, A4 : Collection, A4.Element == A4.Index, A4.SubSequence == A4}}{{33:3-35:51=}}
// expected-warning@+1 {{redeclaration of associated type 'A4' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{27:18= where A4: P0, A4 : Collection, A4.Element == A4.Index, A4.SubSequence == A4}}{{33:3-35:51=}}
associatedtype A4: P0 where A4: Collection,
A4.Element == A4.Index,
A4.SubSequence == A4

// expected-warning@+1 {{redeclaration of associated type 'A5' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{27:18-27:18= where A5: P0b & Class, A5 : Collection, A5.Element : Collection}}{{+0:3-+1:62=}}
// expected-warning@+1 {{redeclaration of associated type 'A5' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{27:18= where A5: P0b & Class, A5 : Collection, A5.Element : Collection}}{{+0:3-+1:62=}}
associatedtype A5: P0b & Class where A5: Collection,
A5.Element: Collection
}
Expand Down
4 changes: 2 additions & 2 deletions test/diagnostics/verifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ let y: Int = "hello, world!" // expected-error@:49 {{cannot convert value of typ
// Wrong fix-it
let z: Int = "hello, world!" as Any
// expected-error@-1 {{cannot convert value of type}} {{3-3=foobarbaz}}
// CHECK: expected fix-it not seen; actual fix-it seen: {{[{][{]}}36-36= as! Int{{[}][}]}}
// CHECK: expected fix-it not seen; actual fix-it seen: {{[{][{]}}36= as! Int{{[}][}]}}

// Expected no fix-it
let a: Bool = "hello, world!" as Any
// expected-error@-1 {{cannot convert value of type}} {{none}}
// CHECK: expected no fix-its; actual fix-it seen: {{[{][{]}}37-37= as! Bool{{[}][}]}}
// CHECK: expected no fix-its; actual fix-it seen: {{[{][{]}}37= as! Bool{{[}][}]}}

// Unexpected error
_ = foo()
Expand Down