dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.92k stars 4.02k forks source link

IDE: Intellisense: Insert full method call #12363

Open WrongBit opened 8 years ago

WrongBit commented 8 years ago

When you type "object.fu", Intellisense inserts just "function", while full syntax is "object.function();". Why these parens and semicolon are skipped? I know sometimes I should insert arguments, but even in this case for me IDE could help jumping between parens (to continue typing) than skipping all punctuations at all.

Of course I don't ask it as an absolute behavior - let me choice option in IDE settings.

lorenpaulsen commented 3 years ago

@TanvirArjel, you're right. I just assumed the gif above had already implemented that. If we go to the first post in this thread, you'll see the original request says,

When you type "object.fu", Intellisense inserts just "function", while full syntax is "object.function();"

What I've always assumed this meant, and have been waiting for myself, is replicating this long-standing behavior from ReSharper/Rider:

By default, when you choose a method in the completion list JetBrains Rider automatically adds parentheses and sets your caret between them in the position to start typing arguments

https://www.jetbrains.com/help/rider/Coding_Assistance_Typing_Assistance.html#dot_completion

I understand this would affect a primary muscle memory path going back 20 years, but ReSharper users have muscle memory of it working this way, so it still makes sense to have at least an option for it.

CyrusNajmabadi commented 3 years ago

I understand this would affect a primary muscle memory path going back 20 years, but ReSharper users have muscle memory of it working this way, so it still makes sense to have at least an option for it.

This is something we're considering. However, as @sharwell stated, it is not part of the current round for this feature area. Our interest is not in aping other features, but trying to see if we can formulate some nicer approaches altogether that can provide a better experience altogether. As such, some of this work is in the service of not narrowly just being able to close a single issue like this, but coming up with an architecture and design to address many areas of feedback we've gotten in the space.

Thanks!

WrongBit commented 3 years ago

Guys, any announce of this feature? When we can try it?

And one thing to remember ALWAYS: Don't even try to be smarter than all of us. You will never make "one solution fits all". Therefore always give flexible options, where user can select what behaviour he needs (using checkboxes in Options). For example, I need insert of full method call: "object.function();" and cursor after ";". And I don't give a damn about somebody's "muscle memory" - I'm able to move cursor left twice (in case of overloads) and it's OK in my rare cases.

So we already have at least two options:

Hope you're smart not to "hardcode" one behaviour for all of us.

WrongBit commented 3 years ago

Sorry, forgot: It's NOT good to force user to type ";" after intellisense pops up. Compare "Enter" and ";" keys - they are totally different! While Enter I can press not even looking at keyboard, I'll WASTE seconds just to find ";" and accurately press it! In other words, I don't need "help", which forces me to find difficult keys - give me option to insert full function call by "Enter". Thanks!

CyrusNajmabadi commented 3 years ago

Guys, any announce of this feature? When we can try it?

You can try out @sharwell's branch right now.

Therefore always give flexible options, where user can select what behaviour he needs (using checkboxes in Options)

We are going to start with a single model so that we can try it out and see how it feels. As we play around with it, we may or may not add more functionality/options as appropriate.

And I don't give a damn about somebody's "muscle memory"

We do :)

I'll WASTE seconds

That's the benefit of muscle memory. It builds up fast. It may be slower initially, but could turn out to be faster once you get used to it.

give me option to insert full function call by "Enter".

We'll likely consider it. It probably won't be in the first PR, but it may be something we play around with once the team starts using this.

aphexetwine commented 3 years ago

Any idea when this will finally be implemented? It's been pending for the longest.

sharwell commented 3 years ago

@aphexetwine The experiment is already available in 16.10, but we have a long way to go on accuracy of the predictions. One of the problems we face is increased accuracy seems to come with significantly increased cost, which makes it hard to run large-scale statistical evaluations of different heuristics. If you try it out, I'd be interested to hear about the results you observe.

WrongBit commented 3 years ago

@sharwell Not sure what "cost" you're talking about. Seems you try to embed my idea to your engine (which never intended to do it). I ask thing which DO NOT require any computations: just look at func declaration and if it has no args - just insert full method call! Period. While you scratch the heads implementing spaceships, people on earth cannot carry even one buck. I mean you waste time on tasks you probably even not able to solve, trying to do everything "universal". One private AND IMPLEMENTED solution works much better than "universal ways", which are implemented for 1%.

And like I said, don't try to be smarter than we - you simply don't. Use OPTIONS everywhere where you have doubts. One checkbox "[x] I want this behaviour" works much better than your tries to make "one fits all".

WrongBit commented 3 years ago

I installed 16.10 but see no any difference with old dumb VS 16.9; I have Socket and when I type "sock." and select "Close()", just word "Close" is inserted. Where is promised "sock.Close();"??

CyrusNajmabadi commented 3 years ago

have Socket and when I type "sock." and select "Close()", just word "Close" is inserted. Where is promised "sock.Close();"??

Select the item you want, and hit semicolon. We'll insert both the method call and the semicolon.

. Use OPTIONS everywhere where you have doubts.

We have an option here:

image

CyrusNajmabadi commented 3 years ago

We also have:

image

However, this is still an experimental work in progress. We'd def like people to try it out and let us know how well it works for cases of trying to get good argument completion when there are multiple arguments. For the no-arg case, 'semi-colon' completion is the way we're supporting typing a single character to get the call and statement completed fully.

WrongBit commented 3 years ago

@CyrusNajmabadi Do you understand that "semicolon" is the most "strange" solution you colud create?? What is EASIER to press - big Enter or normal semicolon?? THIS is the case where mentioned "muscle memory" come into play - I ALWAYS use Enter to confirm my choice, why you implemented it thru semicolon??? What the sick logic behind??

CyrusNajmabadi commented 3 years ago

What is EASIER to press - big Enter or normal semicolon?

I find semicolon easier. It also better expresses my intent. I do not want statements closed just because I inserted a call. I commonly continue calls in c#.

This allows me to express intent simply and concisely.

Also, many of your posts are violating the .net code of conduct. Please refrain from abusive posts or we will have to take action on this. Thanks!

CyrusNajmabadi commented 3 years ago

@WrongBit please read and follow the guidelines here: https://dotnetfoundation.org/about/code-of-conduct

Thanks!

jakobhviid commented 3 years ago

@CyrusNajmabadi While I do not agree with @WrongBit's choice of wording or sentiment, I do agree that the most common way of implementing this across editors seems to be using enter as a confirmation of choice. This is also how I imagined the implementation of this functionality. (for example Visual Studio, IntelliJ IDEA, Resharper from Jetbrains, and more)

Will there be an option to override the semicolon setting so everyone can have their desired functionality?

I must also mention that non-English keyboards do NOT have semicolons as separate keys, which makes this functionality extra frustrating to use. (For me it is "SHIFT + ,")

My imagined functionality implementation would be pressing enter, and it would add the "), but not necessarily the ";" as I do not necessarily want to end the line just because I want the other side of the closures to be completed just as when you write " and the ending " gets inserted, and the curser ends up in between them. Also, I would be ok with the insertion of the ";" if I could go to the end of the ) of the prior command and write a new command without it inserting an additional ";" at the end.

That being said - the choice to use ";" as the modifier makes this a really bad implementation for international keyboards!!!! Please consider the Enter option.

CyrusNajmabadi commented 3 years ago

Will there be an option to override the semicolon setting so everyone can have their desired functionality?

We'd have to go and design what that option woudl do, but i would not be opposed to further flexibility here.

I must also mention that non-English keyboards do NOT have semicolons as separate keys, which makes this functionality extra frustrating to use. (For me it is "SHIFT + ,")

Thanks for that info. THat was definitely information I wasn't aware of.

My imagined functionality implementation would be pressing enter, and it would add the "), but not necessarily the ";"

I could see us potentially going that route. But i am very curious if that's just better suited to the tab-tab feature we're working on instead.

That being said - the choice to use ";" as the modifier makes this a really bad implementation for international keyboards!!!! Please consider the Enter option.

Definitely. Note: it might be best to address this as a new topic. This one is long and covers so many issues. I think you'd have more success having that particular knob be tweakable with a specific issue to cover it.

Thanks!

jakobhviid commented 3 years ago

@CyrusNajmabadi Thanks for your reply.

In regards to the tab-tab feature, I think that would be acceptable as it fits pretty well with vanilla visual studio (no extensions).

In regards to an alternative option to the ";" key, I can understand your stance of putting it in a separate issue once this is closed. This would also make the issue more clear. I will consider opening a separate issue for this.

If you see an easy way of implementing an option to change it to enter, please consider it. I will test the current implementation once it is out and consider whether it makes sense to create a separate issue at that point.

Thanks for the quick reply, and the implementation contribution! We might not agree on the details of the implementation, but I really appreciate this feature being implemented in any form.

CyrusNajmabadi commented 3 years ago

Thanks for the quick reply, and the implementation contribution! We might not agree on the details of the implementation, but I really appreciate this feature being implemented in any form.

Glad to hear it!

Another thing that might help with discussions is to clarify our stance on options, and features here. It likely does not surprise you, but there are many requests for tweaks/changes/features in this area. What is a staggering challenge is trying to find ways to introduce features that work together cohesively, and which do not cause an exponential increase in testing (due to option/feature combinations) as well as an exponential cost maintenance/muscle-memory cost.

One thing we have to always keep in mind is that once we ship these features with certain behaviors, then if we change tehm in teh future (Even if we considered some part of the behavior buggy), then it can substantially degrade the experience for some users in terms of consistency and comprehensibility. When you have an NMO set of these that can interact with each other, it can effectively become nearly impossible to make any sort of change without breaking someone else.

Furthermore we have to consider what happens if we have a major rewrite or otherwise large architectural change (For example, moving these features to something like LSP). In cases like those, it will be very likely we will have to entirely rewrite these features to sit on another system. This already has happened with things like Roslyn itself, as well as the move to VS's async-intellisense architecture. In cases like that, trying to maintain all the behaviors (including buggy ones that people depend on) can be staggeringly difficult.

So our vast preference here is a set of non-overlapping, orthogonal, composable, well-defined features that we can independently introduce and spec out behaviors for. This allows us to only deal with a linear (and not exponential) cost in terms of introduction, maintenance and refactoring over the lifetime of these products.

We are not loathe to add options because we are not listening to customers, or we think the suggestions are inappropriate. We are loathe to do it in some domains because we know there can be an enormous long term impact on our ability to improve and work in these domains when we do.

--

So, making new issues allows us to think about the small tweaks in isolation and do teh design exercise of ensuring that all these concerns are adequately covered and that we think we can move forward in a way we will not regret down the line.

Thanks!

WrongBit commented 3 years ago

@CyrusNajmabadi "I find semicolon easier."

Said enough. That's why "programmers" like you should never ever make decisions! Your argument is totally stupid, but you try to show it as a norm.

I repeat again for those who thinks "semicolon is easier to type" - 1) visit doctor, he can heal you from LYING 2) Any feature you implement ALWAYS follow with checkbox [x] Behave normal or "Cyrus" way. Only this way we can avoid stupid (and hardcoded) decisions and get something helpful out of VS.

WrongBit commented 3 years ago

@jakobhviid "That being said - the choice to use ";" as the modifier makes this a really bad implementation for international keyboards!"

You forgot US mentality: on the Earth there is americans and "the others". No need to think extensively about russians, poland, german people.

I don't know why you don't want ";" after the call - what you gonna write after "Close()"?? One more "Close"???

Rule is so simple that even dumb child realise it: if func has no args and has "void" return, no any continuation is possible! So just put ";" and job is done. And even if type is not "void", MUCH easier to press Enter, then Backspace(also big, easy key), than finding ";".

jakobhviid commented 3 years ago

@WrongBit , you should argue your case to CyrusNajmabadi instead of attacking him. Not everyone is aware of how the rest of the world works, so inform instead of attacking him personally. It is just spreading your bad mood. Nothing constructive comes out of it.

In regards to closing with ; its OK as long as it does not accumulate multiple ; if you add new method calls to the line.

aphexetwine commented 3 years ago

I would love to try these features and give you my impressions. Is there any way I can make this work in Visual Studio Code?

WrongBit commented 3 years ago

@jakobhviid : There is one simple rule: follow the common sense. When guy tells me "semicolon is EASIER to type than Enter" - sorry, this guy has no common sense and must not participate in the discussion. This is tech resource, we have no time to argue with clowns.

Feature already implemented in VS 16.10, but implemented the worst way. It means it takes a whole month to fix this idiocity (if it will be fixed at all). And all WASTED TIME is because MS people DO NOT LISTEN us. They just drop any nonsense in the thread and make smart face. THIS is counter-productive, not my words!!

jakobhviid commented 3 years ago

Thanks for the quick reply, and the implementation contribution! We might not agree on the details of the implementation, but I really appreciate this feature being implemented in any form.

Glad to hear it!

Another thing that might help with discussions is to clarify our stance on options, and features here. It likely does not surprise you, but there are many requests for tweaks/changes/features in this area. What is a staggering challenge is trying to find ways to introduce features that work together cohesively, and which do not cause an exponential increase in testing (due to option/feature combinations) as well as an exponential cost maintenance/muscle-memory cost.

One thing we have to always keep in mind is that once we ship these features with certain behaviors, then if we change tehm in teh future (Even if we considered some part of the behavior buggy), then it can substantially degrade the experience for some users in terms of consistency and comprehensibility. When you have an N_M_O set of these that can interact with each other, it can effectively become nearly impossible to make any sort of change without breaking someone else.

Furthermore we have to consider what happens if we have a major rewrite or otherwise large architectural change (For example, moving these features to something like LSP). In cases like those, it will be very likely we will have to entirely rewrite these features to sit on another system. This already has happened with things like Roslyn itself, as well as the move to VS's async-intellisense architecture. In cases like that, trying to maintain all the behaviors (including buggy ones that people depend on) can be staggeringly difficult.

So our vast preference here is a set of non-overlapping, orthogonal, composable, well-defined features that we can independently introduce and spec out behaviors for. This allows us to only deal with a linear (and not exponential) cost in terms of introduction, maintenance and refactoring over the lifetime of these products.

We are not loathe to add options because we are not listening to customers, or we think the suggestions are inappropriate. We are loathe to do it in some domains because we know there can be an enormous long term impact on our ability to improve and work in these domains when we do.

--

So, making new issues allows us to think about the small tweaks in isolation and do teh design exercise of ensuring that all these concerns are adequately covered and that we think we can move forward in a way we will not regret down the line.

Thanks!

Thank you very much for this reply and insight. It makes a lot of sense.

CyrusNajmabadi commented 3 years ago

I would love to try these features and give you my impressions. Is there any way I can make this work in Visual Studio Code?

@333fred ?

CyrusNajmabadi commented 3 years ago

@WrongBit abusive behavior is not allowed here. Please abide by the .net code of conduct: https://dotnetfoundation.org/about/code-of-conduct

I don't want to have to escalate things here, but I will have to unless we can bring the conversation back to a civil place. Thanks!

CyrusNajmabadi commented 3 years ago

Thank you very much for this reply and insight. It makes a lot of sense.

You're welcome!

CyrusNajmabadi commented 3 years ago

In regards to closing with ; its OK as long as it does not accumulate multiple ; if you add new method calls to the line.

I believe this should work as you have asked. If it doesn't, definitely let us know!

333fred commented 3 years ago

I would love to try these features and give you my impressions. Is there any way I can make this work in Visual Studio Code?

@333fred ?

Not easily. Vscode has no way of inserting different completions based on what key completed the insertion. It might be possible with the async completion experiment we've been trying though, I'll have to think about it.

sharwell commented 3 years ago

I do agree that the most common way of implementing this across editors seems to be using enter as a confirmation of choice.

This is absolutely correct, but it also doesn't apply here to the degree one might think. Historically, most IDEs have adopted Enter as the primary completion list trigger, while Visual Studio has adopted Tab instead. This is a design decision going back multiple decades. Remember that the goal for this feature is not to copy of a different IDE which works in a fundamentally different way, but instead to provide the feature in a manner most natural to users who historically only worked with Visual Studio.

I started out as a primary Visual Studio user, but spent a few years in the middle of my career working on Java code. I felt the opposite pain when the available IDEs didn't allow me to use Tab to complete items. Unfortunately, there are both technical and conceptual differences that make it extremely difficult to interchange these commands (e.g. via an option), and outside an option it's important with keep the design in line with the primary historical behavior for the environment we are working within.

Once we are more comfortable with the high-level support for argument completion, one thing we want to experiment with is using a single Tab for argument completion instead of requiring it twice. This would provide the easiest trigger for the feature while still aligning with Visual Studio's use of Tab over Enter. It would need to be an option which is disabled by default to avoid interfering with long-standing muscle memory.

jakobhviid commented 3 years ago

@sharwell The more I think of it, I actually think you are correct. I actually started my professional career with C# and Visual Studio. But now that I think of it, Resharper was always one of our most used tools. Upon further investigation, I found that reshaper actually changes the visual studio functionality so that Enter works too instead of Tab. Generally Jetbrain tools seem to tend to use Enter.

I can see how this can be the core of the dispute in regards to what keys are used for completion. I still hold the strong opinion that enter should be supported at some point though.

Thank you for your astute insight here.

jmarolf commented 3 years ago

I'll just tag @mikadumont in this

I can see how this can be the core of the dispute in regards to what keys are used for completion. I still hold the strong opinion that enter should be supported at some point though.

@mikadumont has the VS editor team given any thought to having different completion behavior for folks coming from different editors?

jakobhviid commented 3 years ago

@jmarolf that is a good point. I know they have different key maps as extensions now, but I do not know how that integrates with Roslyn.

CyrusNajmabadi commented 3 years ago

@mikadumont has the VS editor team given any thought to having different completion behavior for folks coming from different editors?

Enter is different in that it's an extensibility point that goes through the normal commanding system. So any plugin could be involved here to intercept and handle enter however it wants. tab on the other hand is special. It's extremely baked into completion and cannot be overridden (unless something has changed)

IvanG96 commented 3 years ago

Hi everyone. thank you for all your hard work on this feature. I've had a chance to play around with it and 'd like to share my feedback.

  1. In general it works nice. Looks like a good start as for me.
  2. Currently Tab-Tab works only "once". The use case is simple. I have 2 methods:

    public string InnerMethod(object data) { return null; } public void RootMethod(string data2, string data3) { } I'd like to write something like this: RootMethod(InnerMethod("test"), "test2");

    • start typing method name (method contains arguments)
      • i can complete method call (RootMethod in my example) and open arguments session using Tab-Tab(works as expected)
      • when i pass as arguments result of some other method call (InnerMethod) or new object created via constructor, Tab-Tab doesn't work on these calls but jumps to the next argument of RootMethod. Living me with code like this: RootMethod(InnerMethod, |null);
      • however if i return caret back to RootMethod(InnerMethod|, null) Tabstarts working and open arguments session for InnerMethod. Would it be possible to support such inline cases to open another arguments session inside current?
  3. Would be nice to have similar functionality to complete methods\constructors with generic type parameters
TanvirArjel commented 2 years ago

It is half of 2022 and still, this most wanted very basic feature has not been implemented. :'(

LexaGV commented 2 years ago

I'm not sure in all those statuses.... committed... proposed... WHEN (after 6 years of waiting) we can test this feature, implemented normal way? (thru Enter)

IXLLEGACYIXL commented 2 years ago

is there nwo an optino to enable it ?

OzanDost commented 1 year ago

This is the feature that keeps me switching from Rider to VSCode. Js, Ts, C++ and python extension all have options to enable this behaviour. Any update on this 7 year issue would be amazing.

Arman-Espiar commented 1 year ago

still nope in 17.5 version update in vs 2022 lol

estnml commented 1 year ago

It's unbelievable that software like VSCode still hasn't added such a feature for C#

CyrusNajmabadi commented 1 year ago

@estnml PRs welcome. This is an open source project that everyone is free to contribute to. :-)

If this is something you're passionate about, we'd love to work with you to make the experience what you want! :-)

alimertcetin commented 1 year ago

@CyrusNajmabadi its been 7 years and nobody couldn't implemented this feature since then?

CyrusNajmabadi commented 1 year ago

@alimertcetin see https://github.com/dotnet/roslyn/issues/12363#issuecomment-1575056559

Thanks!

sharwell commented 1 year ago

WHEN ... we can test this feature, implemented normal way? (thru Enter)

@LexaGV Note that for Visual Studio, Enter is not the normal way to invoke completion. For a user who historically used Visual Studio first and then switched to another IDE (e.g. myself, who worked with Visual Studio from around 2002, and then switched to using IntelliJ/Eclipse/NetBeans professionally sometime after 2010), the use of Enter is every bit unnatural feeling as Tab is for users switching the other direction. I literally felt your pain here (my fingers would hurt at the end of days from the tension of trying to remember to hit Enter instead of Tab).

Deus-nsf commented 10 months ago

Behavior works for the most part except inside if statements for example. Loops seem to exhibit this problem too, for example when you're trying to test a returned value in a while statement.

Atulin commented 8 months ago

I come here from 2024 A.D. and can confirm it's still an issue

sharwell commented 8 months ago

@Atulin This is a broad feature request, of which significant portions have already been implemented, other parts are not really possible, and finally there are many smaller cleanup items that could be implemented. It's not clear which specific item you were checking for when you say "it's still an issue".

Atulin commented 8 months ago

Right. Should've been more clear. Assuming | is the caret:

in the most recent version of VS22

sharwell commented 8 months ago

Foo| autocompletes to Foo| instead of Foo(|)

Foo(| autocompletes to Foo(| instead of Foo(|)

By this, I'm assuming you mean you typed F, o, o, (, and the result was Foo(|. If this is the case, it likely means that automatic brace completion is disabled. Tools → Options... → Text Editor → C# → General → Automatic brace completion