rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.28k stars 1.61k forks source link

Make rust-analyzer more like intellij #2741

Closed spadaval closed 4 years ago

spadaval commented 4 years ago

Introduction

In my day job, I spend a lot of time in intellij. Moving to VS Code + RLS was a real shock, I didn't realize just how much I rely on a few intellij features. Moving to rust-analyzer was much better, but the gap still exists.

The Features

Type hints

Intellij adds type hints to the end of each method in a long fluent builder or functional operation. This makes complex functional operations almost as readable and easy to follow as standard procedural code. It also makes it easier to write such expressions. If your operation isn't working the way you expect, this can help you figure out at which step it broke, and what you should do to fix it.

For example: image

Parameter name hints

IntelliJ adds the formal parameter name as a hint into method calls where the corresponding parameter is a literal value.

While taking booleans as function parameters is generally frowned upon, it is still a fairly common pattern, especially for internal functions. This feature can give us some of the benefits of keyword arguments at no cost.

In many dynamic languages, keyword arguments (e.g f(a='b')) are the answer to this problem. However, they are a foundational feature of a language. They affect the way code is written, how API's are designed, and so on. They also usually require some special semantics to be even close to ergonomic. If they haven't shown up yet, they are unlikely to ever show up in Rust. This feature gives us the readability advantages of keyword arguments at no real cost, and makes most code more readable.

image

Most of the plumbing for the frontend of this feature seems to already be in place for this with the InlayKind enum. So, this change shouldn't require too much refactoring.

Jump to test

If you want to write good tested code, you probably need to frequently jump to the tests for a function to see if they cover a particular behavior you may have altered. Alternatively, a great way to learn about the expected behavior of a function is read its test cases.

In either case, the ability to jump to the corresponding test for a function is very useful.

Great Debugging

IntelliJ lets you quickly run or debug a test with the click of a button (or a hotkey). This is extremely useful when doing test-driven development, or when trying to diagnose a weird failing test case. The Rust debugging experience is currently less than optimal.

I realize this is rather out of scope, but it is something worth looking at in the long term. A good debugging experience is essential for any language.

image

Quick Fixes

IntelliJ can quickly highlight anti-patterns and offer quick fixes. For example, if you write an extremely simple lambda (eg (x) -> x.get()), IntelliJ will offer to change that to a method reference (XClass::get).

There is prior art here, this is basically what rustfix already does. We simply need to make this a more interactive process.

spadaval commented 4 years ago

Also, belated trigger warning: examples are in Java.

bjorn3 commented 4 years ago

Jump to test

How to handle the case where there is no 1 to 1 correspondence between functions and tests?

gilescope commented 4 years ago

@spadaval rust test lense vscode extension works well for codelldb debugger on osx/win/linux.

spadaval commented 4 years ago

@bjorn3 Don't we already do this for Find References? In my mental model, a test is a (special) kind of reference, so that model should work fine.

upachler commented 4 years ago

@spadaval Although I'm sure the authors of rust-analyser are well aware of 'the gap' as you call it, I certainly agree: I come from a Java IDE as well and rely heavily on code completion, and IDE support is key for acceptance of a young language like Rust. So here are my ten cents:

As a relative Rust noob I'm currently toying around with the GTK bindings (gtk-rs), however, these turn out to be really hard to use and even more learn without proper code completion. I know a fair bit about UI libraries in general but not so much about GTK, so I need to search around a lot about how things are named in GTK. RLS was no help at all, but for this use case, neither was rust-analyser. Like RLS, rust-analyser isn't able to enumerate available methods on a struct instance in many cases, forcing me to spend lots of time in the API docs rather than simply reading it from method suggestions in the IDE. I assume that gtk-rs is particularly hard to parse for rust-analyser and RLS alike because it relies heavily on traits, closures and macros, which seem to be a real challenge for an on-demand IDE language model.

This is by no means intended as rant, on the contrary, it's great that so much effort is going into rust-analyser and the rust ecosystem in general, and seeing it grow and thrive as much as it did in such a short amount of time.

However, IDE integration is a major productivity factor when working with a programming language. For example, method suggestions cut down doc lookup times manifold (I'd guess it's 5-10 times, but hat's just my guess). Language ecosystems like C# and Java build on that, making developer productivity a key point for their success.

I think there is a lot of potential for Rust in 'converts' like myself coming from these languages, and improving programmer productivity via IDE integration is a key factor for getting these people on board. Estimates for 2019 suggest there are 7,5M Java developers out there - who knows how many would convert to Rust, if you only make it easy enough for them?

So @spadaval, I hope that this ticket will generate attention in the right places, so rust-analyser will receive even more funding/effort in the future - so that in the end, IDE support for Rust will be as good as we're used to from IntelliJ IDEA and friends.

Uwe

spadaval commented 4 years ago

I want to be clear on this; I'm not suggesting that the rust-analyzer authors have somehow failed at something. This tool is pretty great, and it's leaps and bounds ahead of many others. It would be silly to expect an experimental open-source tool to have feature parity with a commercial IDE from an enterprise juggernaut like JetBrains, nor is that the goal the project should have. I mentioned IntelliJ simply because is just the one that I work with the most (and the most successful).

However, I do think that IDE productivity is crucial to a language's success. Java is an incredibly complex and verbose language. It's not very ergonomic in many ways, and there are plenty of ways to break things in subtle ways. IntelliJ's amazing code completion, type hints, method lookups during typing, highlighting (and quick fixes) of common errors and anti-patterns, and easy boilerplate generation make working in Java actually more pleasant than many higher-level languages like Python.

Great IDE tools could also help reduce Rust's learning curve, by offering tools to do things like refactoring (or like the assists, which are great) or highlighting bad code and providing explanations and alternatives.

spadaval commented 4 years ago

Also, I should clarify that this issue is not a feature request; I intend to add these things myself. I'm basically just asking for comments, suggestions, and other inputs before I start.

gilescope commented 4 years ago

I’m sure there’s some easy issues to get started with if you have any spare time - if not you will appreciate even more that the dev is constrained by spare time/ funding.

I’ve been watching from the side lines, but it’s come on a lot over the last 6 months. The more we can support the project in whatever ever way we can, the faster we will all get what we want. And I’m pretty sure we all want the same thing - world class IDE experiences.

On Sun, 5 Jan 2020 at 17:31, Sumeet Padavala notifications@github.com wrote:

Also, I should clarify that this issue is not a feature request; I intend to add these things myself. I'm basically just asking for comments, suggestions, and other inputs before I start.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rust-analyzer/rust-analyzer/issues/2741?email_source=notifications&email_token=AAGEJCDQ6TA7SVNGG4SGNQLQ4IKQRA5CNFSM4KCP5VLKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEID3R7Y#issuecomment-570931455, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGEJCB2PPRCPYSJPQB6FJLQ4IKQRANCNFSM4KCP5VLA .

matklad commented 4 years ago

To clarify, I am definitely aware about IntelliJ capabilities :D

https://github.com/intellij-rust/intellij-rust/graphs/contributors

A reason behind many of the papercuts is that Vs Code / LSP just doesn't have official API for this (in contrast to IntelliJ, which both has a much more extensive array of existing extension points, as well as an open-world API with which you can do whatever). From the originally mentioned features, only quick fixes are present in the LSP.

That said, rust-analyzer explicitly tries to provide APIs for the theoretically all-powerful client, and is deliberately not tied to a particular protocol. We also abuse LSP/Vs Code to hack features which aren't officially supported. (type hints are a good example of this).

So, I am all for identifying specific missing features, filing them as separate issues and doing more polish. In general, the low-level infra in rust-analyzer is pretty powerful already, and a lot of value can be derived by just making stuff on top (ra_ide and ra_assists crates mainly) more powerful.

To go feature-by-feature:

type & parameter hints

It is implemented here. Adding hints for parameter names for literal parameters would be an awesome contribution! Adding type hints to chained method calls might be more involved, but also should be done.

Jump To Test

I have a hunch that this would be much less helpful in Rust that in Java, because there's typically no class Foo / class FooTest correspondence, and unit tests are typically in the same module anyway. If we are to add this feature, we should make use of symbol_index. Basically, for function foo we should find all functions annotated with test and having foo in the name.

Debug/Run

This is again the feature which VS Code sadly doesn't have an API for. We do provide an ability to run a test/binary via a shortcut (action is called Rust Analyzer: Run) or code lens (vs code analogue for IntelliJ gutter icons). The debugging story is a lot less clear, as we need to integrate not with VS Code itself, but with another extension which provides debuging. That extension, however, already implements detection of rust test functions in an approximate way, so this is also somewhat covered.

Quick Fixes

We have 'em! And this is the area where the biggest amount of polish is required, as we need more assist, and we need to make existing ones more robust (almost every existing assist does not work correctly in some corner cases). The list of assists is here: https://github.com/rust-analyzer/rust-analyzer/tree/1953ac17fd8c93d2145ec3103fd39dd9d6c8fd30/crates/ra_assists/src/assists

to-mas-kral commented 4 years ago

@matklad OT I'm interested in working on the assists. Which new assists do need to be implemented and which assists have bugs ? I haven't done much Rust programming lately, so I'd rather start with something easier though.

matklad commented 4 years ago

I don't have a read-made list, but searching issues reveals some: https://github.com/rust-analyzer/rust-analyzer/search?q=assist&type=Issues

It might also be a good idea to just look through existing assists and check if they can fail in some edge cases (I think most will).

On Fri, 17 Jan 2020 at 12:15, Tomáš Král notifications@github.com wrote:

@matklad https://github.com/matklad OT I'm interested in working on the assists. Which new assists do need to be implemented and which assists have bugs ? I haven't done much Rust programming lately, so I'd rather start with something easier though.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rust-analyzer/rust-analyzer/issues/2741?email_source=notifications&email_token=AANB3M24MJH2CQCXUL2P3ELQ6GHO5A5CNFSM4KCP5VLKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJHLXVI#issuecomment-575585237, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANB3MZLT5NFESKS6YLGJADQ6GHO5ANCNFSM4KCP5VLA .

to-mas-kral commented 4 years ago

Ok, thanks, I'll look into it.

matklad commented 4 years ago

It seems like we actualy have most of the mentioned things implemented in some capacity already?