Skip to content
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

Add a codefix that suggests replacements for unknown identifiers #2106

Merged
merged 6 commits into from
Dec 27, 2016

Conversation

forki
Copy link
Contributor

@forki forki commented Dec 26, 2016

image

  • - Suggestions for FS0039
  • - Suggestions for other errors
  • - Put strings into resx

@forki
Copy link
Contributor Author

forki commented Dec 26, 2016

@vasily-kirichenko could you please take a quick look if this goes into the right direction?

@Krzysztof-Cieslak I think I need to change the error pattern a small bit. We should remember to adjust that next time when ionide updates FCS.

@forki forki force-pushed the suggestfix branch 2 times, most recently from 9027078 to 4e52965 Compare December 27, 2016 10:40
@forki forki changed the title [WIP] Add a codefix that suggests replacements for unknown identifiers Add a codefix that suggests replacements for unknown identifiers Dec 27, 2016
@forki
Copy link
Contributor Author

forki commented Dec 27, 2016

this is ready for review

@vasily-kirichenko
Copy link
Contributor

:)

image

@vasily-kirichenko
Copy link
Contributor

LGTM

override __.RegisterCodeFixesAsync context : Task =
async {
context.Diagnostics
|> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe make fixableDiagnosticIds a Set to faster filtering?

context.Diagnostics
|> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id)
|> Seq.iter (fun x ->
let splitted = x.GetMessage().Split([|"Maybe you want one of the following?"|], StringSplitOptions.None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this string available as a constant somewhere in the compiler? Using it here as literal is fragile in case of future changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already fixed

let suggestions =
splitted.[1].Split([|' '; '\r'; '\n'|], StringSplitOptions.RemoveEmptyEntries)
|> Array.map (fun s -> s.Trim())
let diagnostics = [| x |].ToImmutableArray()
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe choose a more descriptive name instead of x? The lambda is not one or two liner, so it's hard to track what x means.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think each code fix should contain all the diagnostic ids in its "fixing" list. Currently you generate a code fix for each id in context that this code fix supports.

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 think each code fix should contain all the diagnostic ids in its "fixing" list. Currently you generate a code fix for each id in context that this code fix supports.

what do I have to change?

Copy link
Contributor

Choose a reason for hiding this comment

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

I was wrong, forget it.

for suggestion in suggestions do
let codefix =
createCodeFix(
"Replace with " + suggestion,
Copy link
Contributor

Choose a reason for hiding this comment

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

"Replace with" should be put to the project's *.rc file, see how this is done in other code fixes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already done

createCodeFix(
"Replace with " + suggestion,
context,
TextChange(TextSpan(context.Span.Start, context.Span.End), suggestion))
Copy link
Contributor

Choose a reason for hiding this comment

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

TextSpan(context.Span.Start, context.Span.End) => context.Span

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already done

@vasily-kirichenko
Copy link
Contributor

It still suggests unrelated stuff, like on the screenshot above. How on Earth nativeptr is close to DateT?

@forki
Copy link
Contributor Author

forki commented Dec 27, 2016 via email

@isaacabraham
Copy link
Contributor

Have we moved over to Jaro Winkler?

@forki
Copy link
Contributor Author

forki commented Dec 27, 2016

@isaacabraham yes long time ago

Copy link
Member

@KevinRansom KevinRansom left a comment

Choose a reason for hiding this comment

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

other than splitted this looks good.

|> Seq.filter (fun x -> fixableDiagnosticIds |> Set.contains x.Id)
|> Seq.iter (fun diagnostic ->
let message = diagnostic.GetMessage()
let splitted = message.Split([|maybeString|], StringSplitOptions.None)
Copy link
Member

Choose a reason for hiding this comment

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

splitted is not really a word :-)

The past tense of split is .... split.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lol.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

https://en.m.wiktionary.org/wiki/splitted it says I'm nonstandard or archaic. Guess I can live with that.

Anyways, will fix tomorrow.

|> Seq.iter (fun diagnostic ->
let message = diagnostic.GetMessage()
let splitted = message.Split([|maybeString|], StringSplitOptions.None)
if splitted.Length > 1 then
Copy link
Member

@KevinRansom KevinRansom Dec 27, 2016

Choose a reason for hiding this comment

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

This feels somewhat icky ... we should consider adding to the compiler service an improved method of transmitting error information to the IDE.

For example:

  • I'm not at all sure how this string parsing we do in these fixers would work on a language like Arabic which works left to right. (hmmm I meant right to left)

Obviously that's not specific to this PR ... but we should consider an improvement.

Kevin

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Absolutely. Parsing error messages is definitely the wrong way to do it (I think this specific case could also work in Arabic - because we concatenate the error message from left to right).

That said: it is an easy way to do it. And it works in practice. We already love to use it in ionide

@KevinRansom KevinRansom merged commit aef573e into dotnet:master Dec 27, 2016
@forki forki deleted the suggestfix branch December 28, 2016 08:16
nosami pushed a commit to xamarin/visualfsharp that referenced this pull request Jan 26, 2022
…net#2106)

* Add a codefix that suggests replacements for unknown identifiers

* Use sets

* Better naming

* Change prediction text a bit to better work with MSBuild errors

* cleanup

* Suggest id if it is an infix
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.

5 participants