Skip to content

[Diagnostics] Improve {{none}} fix-it verifier #30791

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

Merged
merged 12 commits into from
Apr 9, 2020

Conversation

omochi
Copy link
Contributor

@omochi omochi commented Apr 3, 2020

This PR improve {{none}} fix-it verifier.

Currently, it means that no fix-it is expected.

I improve it to mean that no more fix-it is expected when use it with normal fix-it verifier at same time.

For example:

func labeledFunc(aa: Int, bb: Int) {}

func test() {
  // (1)
  labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15-18=aa}}
  
  // (2)
  labeledFunc(aax: 0, bbx: 1) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{15-18=aa}}
}

They means that diagnosed fix-its include {{15-18=aa}} at least.
They doesn't care about whether more other fix-its are emitted.
Actually (2) emits second fix-its for label bbx:, but it doesn't affect anything.

I introduce new feature for such situation to check strictly fix-its are just equal to expected.
For example:

func test() {
  // (3)
  labeledFunc(aax: 0, bb: 1) // expected-error {{incorrect argument label in call (have 'aax:bb:', expected 'aa:bb:')}} {{15-18=aa}} {{none}}
  
  // (4)
  labeledFunc(aax: 0, bbx: 1) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{15-18=aa}} {{none}}
}

With above code, (3) is passed verification but (4) is not.

We can check fix-its more strictly.


Original code doesn't support using it with normal fix-its.

This is result from Xcode11.4

a.swift:3:135: error: expected no fix-its; actual fix-it seen: {{13-16=aa}} {{21-24=bb}}
labeledFunc(aax: 0, bbx: 1) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{13-16=aa}} {{none}}
                                                                                                                                      ^~~~~~~
                                                                                                                                      {{13-16=aa}} {{21-24=bb}}

@CodaFi @gregomni @owenv Could you review this?

@omochi omochi requested review from CodaFi, owenv and gregomni April 3, 2020 10:42
@omochi
Copy link
Contributor Author

omochi commented Apr 3, 2020

@swift-ci Please smoke test

Copy link
Contributor

@owenv owenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how often this will be used, but I think you're right that it could be useful for some of the diagnostics like argument renaming which produce many fix-its. I have a few comments which I think could help improve the clarity of the code.

@@ -16,7 +16,7 @@ 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-its: {{[{][{]}}36-36= as! Int{{[}][}]}}
// CHECK: expected fix-it not seen; actual fix-it seen: {{[{][{]}}36-36= as! Int{{[}][}]}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make sense to be actual fix-its seen: because it can have more than one? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I will support plural form.

@omochi
Copy link
Contributor Author

omochi commented Apr 4, 2020

I have exactly been working on improving the diagnosis of argument labels recently.
I wanted this feature because I had to fix a lot of test cases in that work.
#30444

@omochi
Copy link
Contributor Author

omochi commented Apr 4, 2020

@owenv @LucianoPAlmeida

I updated implementation.

I followed the points except for the following.
#30791 (comment)

I think it's getting better.

@omochi omochi requested a review from owenv April 4, 2020 14:43
Copy link
Contributor

@owenv owenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new direction, I just have a few more small comments. Also, thanks for adding all the new tests!

Comment on lines 566 to 568
auto makeActualFixitsPhrase =
[&](ArrayRef<DiagnosticInfo::FixIt> actualFixits,
std::string &actualFixitsStr) -> std::string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this would be cleaner if it returned an std::pair of actualFixitsStr and the phrase instead of using actualFixitsStr as an out parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I did it.

Comment on lines +606 to +631
if (replStartLoc[-1] == ' ') {
replStartLoc--;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: a comment explaining why this is needed might be nice for future readers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 572 to 576
if (actualFixits.size() >= 2) {
str += "s";
}
str += " seen: ";
str += actualFixitsStr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine, but using llvm::Twine might make the concatenation a little more efficient

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I did it.

Comment on lines 622 to 624
const char *noneStartLoc =
expected.ExpectedEnd -
(fixitExpectationNoneString.size() + 4) /* length of '{{none}}' */;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the verifier currently requires {{none}} is at the end. I think it probably makes sense to report an error if it does not. I think we can diagnose this just before we start parsing a fix-it on line 469 if Expected.noExtraFixitsMayAppear is already true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that check is needed too.
I was going to make it another PR.

I implemented it and added test case.

@omochi
Copy link
Contributor Author

omochi commented Apr 5, 2020

Thank you for review. I will check tomorrow.

@omochi
Copy link
Contributor Author

omochi commented Apr 6, 2020

I updated 😄

@swift-ci Please smoke test

@omochi omochi requested a review from owenv April 6, 2020 07:44
Copy link
Contributor

@owenv owenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left one optional comment for rewording a message, but this looks great. Thank you!

@omochi
Copy link
Contributor Author

omochi commented Apr 8, 2020

@owenv Thanks for your review and approval.
I updated message and fix some test cases for new feature.
After CI will passed, I will squash commits into one and merge PR.

@swift-ci Please smoke test

By the way, I granted a commit access recently, but a bot doesn't respond at all.
I hope it works this time.

@owenv
Copy link
Contributor

owenv commented Apr 8, 2020

@swift-ci please smoke test

// it returns actual fix-its string and diagnostic phrase
auto makeActualFixitsPhrase =
[&](ArrayRef<DiagnosticInfo::FixIt> actualFixits)
-> std::tuple<std::string, std::string> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::tuple is not quite the vocabulary type you want to use here. Please use a real struct with named fields so we can avoid all of that tuple unpacking noise below and get some decently self-documenting code here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it 🙂

}

bool matchedAllFixIts =
expected.Fixits.size() == FoundDiagnostic.FixIts.size();
bool isUnexpectedFixitsSeen =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: const

@omochi
Copy link
Contributor Author

omochi commented Apr 9, 2020

@CodaFi Thank you for review!
I'm grad to get your comment before merge.
I will update.

@omochi
Copy link
Contributor Author

omochi commented Apr 9, 2020

@shahmishal Thanks for fixing my CI trigger.

@swift-ci Please smoke test

@CodaFi
Copy link
Contributor

CodaFi commented Apr 9, 2020

@CodaFi CodaFi merged commit a07b35a into swiftlang:master Apr 9, 2020
@omochi
Copy link
Contributor Author

omochi commented Apr 10, 2020

Thank you all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants