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

Rework code action service #899

Merged
merged 1 commit into from
Jun 28, 2017

Conversation

DustinCampbell
Copy link
Contributor

This change reworks how we compute code fixes and refactorings. Much of this is just basic refactoring and clean up, but there are substantial changes to to code fixes are computed. Now, we'll return code fixes when there are multiple diagnostics with overlapping spans. For example, consider this scenario:

class C
{
    void M()
    {
        StringBuilder
    }
}

There are three diagnostics at the position immediately following StringBuilder:

  1. CS1001: Identifier expected
  2. CS1002: ; expected
  3. CS0246: The type or name 'StringBuilder' could not be found

The problem is that the first two diagnostics have a zero-width span immediately following StringBuilder, but the last diagnostic has the same span as StringBuilder. Previously, if the code action service was called with the line and column after StringBuilder, only the first two diagnostics would be considered for fixes because their spans are an exact match. However, it's the last diagnostic that we really want because that's the one for which the 'add import' code fix is triggered by. This change ensures that we'll consider all relevant diagnostics when computing code fixes.

This change reworks how we compute code fixes and refactorings. Much of this is just basic refactoring and clean up, but there are substantial changes to to code fixes are computed. Now, we'll return code fixes when there are multiple diagnostics with overlapping spans. For example, consider this scenario:

```C#
class C
{
    void M()
    {
        StringBuilder
    }
}
```

There are three diagnostics at the position immediately following `StringBuilder`:

1. CS1001: Identifier expected
2. CS1002: ; expected
3. CS0246: The type or name 'StringBuilder' could not be found

The problem is that the first two diagnostics have a zero-width span immediately following `StringBuilder`, but the last diagnostic has the same span as `StringBuilder`. Previously, if the code action service was called with the line and column after `StringBuilder`, only the first two diagnostics would be considered for fixes because their spans are an exact match. However, it's the last diagnostic that we really want because that's the one for which the 'add import' code fix is triggered by. This change ensures that we'll consider all relevant diagnostics when computing code fixes.
DustinCampbell added a commit to DustinCampbell/vscode-csharp that referenced this pull request Jun 28, 2017
Fixes dotnet#1605

When calling CodeActionProvider.provideCodeActions(...), VS Code passes the range of the word to the left of the editor caret if there's no selection. This ends up causing refactorings like Extract Method to be offered even when the user hasn't selected any code. Now, we'll check to see if there's actually a selection and use that instead of the range that's given.

To fully fix this issue, I've made several changes in OmniSharp: OmniSharp/omnisharp-roslyn#899. Once that goes in, we'll need to update the version of OmniSharp used by C# for VS Code.
Copy link
Member

@filipw filipw left a comment

Choose a reason for hiding this comment

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

very nice improvement.

would also be cool to one day tap into Roslyn's code action ordering

@DustinCampbell
Copy link
Contributor Author

would also be cool to one day tap into Roslyn's code action ordering

Yup, I'm hoping to look at that soon.

@DustinCampbell
Copy link
Contributor Author

And FWIW, if I add extension ordering, it'd be temporary. That's really an implementation detail that should be handled by a proper service from Roslyn.

{
internal static class DictionaryExtensions
{
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueGetter)
Copy link
Member

Choose a reason for hiding this comment

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

someone add this to the BCL. 🔮

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right? 😄

@DustinCampbell
Copy link
Contributor Author

Thanks guys!

@DustinCampbell DustinCampbell merged commit d397668 into OmniSharp:dev Jun 28, 2017
@DustinCampbell DustinCampbell deleted the fix-code-fixes branch August 30, 2017 19:13
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.

3 participants