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

Intellisense for cast, indexers and operators #47511

Merged
331 commits merged into from Mar 19, 2021

Conversation

MaStr11
Copy link
Contributor

@MaStr11 MaStr11 commented Sep 7, 2020

Fixes #46266

rFXRdsGBfI

A test class with indexers, conversions, and operators can be found here:
https://gist.github.com/MaStr11/b87367ac2cad5d7554d89a8c8379081b

@MaStr11
Copy link
Contributor Author

MaStr11 commented Sep 11, 2020

@CyrusNajmabadi I started a draft to see what building blocks are needed to achieve this. I started with enhancing SymbolCompletionProvider.cs but I'm not sure whether that is the right place to implement this. The symbols for the completion list are calculated by the CSharpRecommendationServiceRunner.cs and I can't tell whether we should add symbols there (see 495ce89. I find the service quite complicated and I don't know if symbols like indexers and operators should be added there or in a separate place). The other problem is, that SymbolCompletionProvider has some simple rules on how to apply the completion (basically only adding text). But in the indexer/operator case we need to replace previous tokens (see screencast above), so I needed to override GetChangeAsync.

I think it would be better to implement this feature in its own CompletionProvider without relying on the CSharpRecommendationServiceRunner. I think the best candidate would be AbstractSymbolCompletionProvider or even LSPCompletionProvider.

What do you think is the best way forward?

PS: No need to review the PR. The code is only prototyped to get the screencast running.

Copy link
Contributor Author

@MaStr11 MaStr11 left a comment

Choose a reason for hiding this comment

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

@CyrusNajmabadi Please see my last comment from 3 days ago #47511 (comment).

I gave a dedicated CompletionProvider a try in 31f1090. This means, that the explicit cast completion is now duplicated. I did this, so you can compare both approaches.

Implementing a dedicated provider seems preferable to me, because of:

  • Simpler fine control over the circumstances, when to offer operator/indexer symbols. syntaxTree.FindTokenOnLeftOfPosition(position).IsKind(SyntaxKind.DotToken) seems to be sufficient and simple. The CSharpRecommendationServiceRunner, on the other hand, does a lot of work before actually calculating the symbols to provide and I think it will be complicated to decide there if the new symbols should be added or not.
  • SymbolCompletionItem contains a lot of functionality needed (GetDescriptionAsync, GetSymbolsAsync, etc.). This limits the need to access functionality provided by SymbolCompletionProvider and its base class AbstractRecommendationServiceBasedCompletionProvider
  • SymbolCompletionProvider adds "SymbolInfo" as a property to the CompletionItem, but at least for the conversion, it seems preferable to add "SymbolEncoding" instead.
  • The TextChanges to apply are more complicated than what SymbolCompletionProvider provides and GetChangeAsync needs to be overridden anyway.

I need some feedback now, which of the both are more appropriate. Once I have directions on that, I can start writing tests (and fix the failing tests).

@CyrusNajmabadi
Copy link
Member

Implementing a dedicated provider seems preferable to me,

this makes a ton of sense to me. I will try to get to reviewing this soon :)

@CyrusNajmabadi CyrusNajmabadi self-assigned this Sep 14, 2020
@CyrusNajmabadi
Copy link
Member

(i was on a vacation, so i didn't see this stuff until now).

@MaStr11
Copy link
Contributor Author

MaStr11 commented Sep 16, 2020

@CyrusNajmabadi Can I get a first review, please? If you want to play around with it, I created a gist with a class with indexers, operators, and conversions here:

https://gist.github.com/MaStr11/b87367ac2cad5d7554d89a8c8379081b

These parts are implemented:

  • explicit user-defined conversions
  • indexer

The explicit conversion is fixed like so:

// Before
expr.$$
// After
((float)expr).$$

But the spec in #46266 defined it, like so:

// Before
expr.$$
// After
(float)expr$$

I think both approaches are sensible. Do you want me to change it according to the spec (I missed the spec until I was finished)?

If there is more than one indexer defined, I currently suggest both overloads:
image
I think it should only show one overload and the and one more overload hint. What do you think?

There is a bug with the completion currently:
Steps to reproduce

  1. Open completion after the dot
  2. Type some text
  3. Commit the conversion

Expected

After typing starts, the conversion suggestion is no longer shown.

Actual

The conversion suggestion stays on the list and can be selected. The first input (f) is highlighted (bold), but the second input (l) is not.

This is something that needs to be fixed along with the sorting (indexer/operator/conversion should go to the end of the list).

Btn2Mr5kzm

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Sep 16, 2020

The explicit conversion is fixed like so:

The way you're doing this is the right way :) we should end with ((foo)bar).$$

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Sep 16, 2020

I think it should only show one overload and the and one more overload hint. What do you think?

I woudl just show this as:

this[]

indicating there's an indexer, using the normal indexer syntax. for methods we don't include parameter types, so i would not include them here. The description for that item will give you that info.

@CyrusNajmabadi
Copy link
Member

The conversion suggestion stays on the list and can be selected. The first input (f) is highlighted (bold), but the second input (l) is not.

that's bizarre. woudl want this fixed. this list should filter and highlight normally :)

@CyrusNajmabadi
Copy link
Member

Also, once committed, we should not end up with:

image

We'd want to end with ((float)w).$$

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

Looking really good so far! :)

@CyrusNajmabadi
Copy link
Member

LMK when you want a pass.

if (opPosition.HasFlag(OperatorPosition.Infix))
return await ReplaceTextAfterOperatorAsync(document, item, text: $" {item.DisplayText} ", cancellationToken).ConfigureAwait(false);

if (opPosition.HasFlag(OperatorPosition.Postfix))
Copy link
Member

Choose a reason for hiding this comment

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

So increment/decrement operator will always complete as postfix (also as displayed in inline description). Not sure we make the enum a flag then, it might make the intention clearer w/o that.

@@ -7688,6 +7688,65 @@ class C
End Using
End Function

<WorkItem(47511, "https://github.com/dotnet/roslyn/pull/47511")>
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub ConversionsOperatorsAndIndexerAreShownBelowMethodsAndPropertiesAndBeforeUnimportedItems()
Copy link
Member

@genlu genlu Mar 19, 2021

Choose a reason for hiding this comment

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

Please test the commit and filter behavior for the new provider, since these tests go through Editor layer and act more like integration tests for completion.

}

var opCharacters = ImmutableArray.CreateRange(filterCharacters);
s_operatorRules = CompletionItemRules.Default
Copy link
Member

Choose a reason for hiding this comment

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

Are there tests for the commit/filter char modification?

};
}

public override async Task<CompletionDescription?> GetDescriptionAsync(
Copy link
Member

Choose a reason for hiding this comment

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

Please add some tests for description.

Copy link
Member

@genlu genlu left a comment

Choose a reason for hiding this comment

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

LGTM besides some minor suggestions. Can't wait to try this out, thanks! :)

IDE: CommunityPR automation moved this from BuddyAssigned to LGTM Mar 19, 2021
@CyrusNajmabadi
Copy link
Member

Will add tests tahnks!

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Auto-approval

@ghost ghost merged commit ff512d2 into dotnet:main Mar 19, 2021
IDE: CommunityPR automation moved this from LGTM to March-2021 Mar 19, 2021
@ghost ghost added this to the Next milestone Mar 19, 2021
@CyrusNajmabadi
Copy link
Member

ack. i thought i'd already pushed a change, so auto-merge wouldn't merge in. but it was on a machien that hadn't pulled, so the push got rejected. i will make a followup PR for this (including hte ability to disable this feature if we want).

@CyrusNajmabadi
Copy link
Member

thanks @MaStr11 for the great feature. @jinujoseph @mikadumont @kendrahavens for visibility on this! :)

MaStr11 added a commit to MaStr11/roslyn that referenced this pull request Mar 23, 2021
Follow up to dotnet#47511

I missed placing the `[Fact]` attribute on one test method. @CyrusNajmabadi
@allisonchou allisonchou modified the milestones: Next, 16.10.P2 Mar 29, 2021
333fred added a commit to 333fred/omnisharp-roslyn that referenced this pull request Apr 23, 2021
The recent completion rewrite makes completion faster for a large number of cases, but it has a couple of issues:

* Any completion provider that needs to make edits beyond the few we've special cased doesn't work correctly. Roslyn is looking to add more of these, such as dotnet/roslyn#47511.
* Completion providers that we do special case can be _slow_. Override and partial method completion in big types is painful, taking over a minute to show up sometimes.

To resolve this, I've added support for async edits by adding a new completion end point: /completion/afterInsert. It takes the item that was inserted, the file, and the new cursor position. It relies on the InsertText that was inserted still allowing for resolving the completion in the same way as before, so I had to force a few providers that don't behave well here to be eagerly resolved, regardless. I also kept import completion using the standard /completion/resolve step to resolve extra edits, as they don't need to modify the current cursor location at all.
333fred added a commit to 333fred/omnisharp-roslyn that referenced this pull request Apr 25, 2021
 The recent completion rewrite makes completion faster for a large number of cases, but it has a couple of issues:

 * Any completion provider that needs to make edits beyond the few we've special cased doesn't work correctly. Roslyn is looking to add more of these, such as dotnet/roslyn#47511.
* Completion providers that we do special case can be _slow_.  Override and partial method completion in big types is painful, taking over a minute to show up sometimes.

To resolve this, I've added support for async edits by adding a new completion end point: /completion/afterInsert. It takes the item that was inserted, the file, and the new cursor position. It relies on the InsertText that was inserted still allowing for resolving the completion in the same way as before, so I had to force a few providers that don't behave well here to be eagerly resolved, regardless. I also kept import completion using the standard /completion/resolve step to resolve extra edits, as they don't need to modify the current cursor location at all.
@jinujoseph jinujoseph moved this from March-2021 to Completed 2021 in IDE: CommunityPR Jan 9, 2022
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE auto-merge Community The pull request was submitted by a contributor who is not a Microsoft employee. Feature Request
Projects
IDE: CommunityPR
  
Completed 2021
Development

Successfully merging this pull request may close these issues.

Explicit cast options in intellisense in C #
10 participants