rust-analyzer icon indicating copy to clipboard operation
rust-analyzer copied to clipboard

Feature request: Intellisense in Jupyter cells

Open Milo123459 opened this issue 4 years ago • 9 comments

Hi, I'm writing a notebook using Rust with Jupyter and I want to use rust-analyzer to get intellisense in my rust cells. I'm using the VSCode extension for Jupyter. Do you think this could be implemented? Thanks.

Milo123459 avatar Jun 20 '21 13:06 Milo123459

I was recently trying to figure this out, and ran into a bit of a problem because there seems to be a difference between normal Rust code and evcxr Rust code: whether lines are allowed to end in semicolons.

In evcxr, a semicolon-free line is okay and will cause the output to be displayed in the notebook, while adding the semicolon will quiet the output. For example, suppose I have this code:

fn five() -> i32 {
    5
}
five()

If you run this in evcxr it will display 5. However, rust-analyzer doesn't like it. It reports mismatched types: expected (), found i32. Fair enough, but I do want to allow non-() expressions at the top level!

Moreover, rust-analyzer seems to stop parsing after a line like this. If you put another line of code at the end, you get a diagnostic that says unexpected token.

I'm contemplating two solutions to this, and would love to get some feedback on what would be best.

  1. Parse the Rust code with tree-sitter or similar and stick semicolons in the appropriate places before presenting the code to rust-analyzer. And suitably transform all LSP messages going to and fro. (Kind of scary)
  2. Teach rust-analyzer to have a "notebook mode" where it understands that semicolon-free expressions at the top level are okay?

CC @davidlattimore who indicated some interest over in #5141 :)

thomasjm avatar Nov 29 '23 07:11 thomasjm

Can it be wrapped in a function like this:

fn f() -> ! {
  fn five() -> i32 {
      5
  }
  five()
}

edwin0cheng avatar Nov 29 '23 07:11 edwin0cheng

Hmm, I just tried that in a simple Rust project and rust-analyzer doesn't seem to like it:

  • On the exclamation point I get a warning expected ! because of return type [E0308]
  • On the final five() line I get the mismatched types error again

I'm far from a Rust expert though so could easily be missing something. ~~FWIW we could equally well have more semicolon-free lines scattered throughout like this:~~

fn five() -> i32 {
    5
}
five()
println!("hello");
five()

thomasjm avatar Nov 29 '23 08:11 thomasjm

Given the final expression is to be printed anyways the wrapping could always be something like

fn main() {
    let eval = {
        // cell content goes here
    };
    println!("{eval}");
}

or whatever the desired way to handle this is. I don't know how evcxr works. Note though that any modifications for this to the rust-analyzer are unlikely to be accepted, the only thing I expect to be modified here is the vscode extension at best. That is at least my wishful thinking, whether that is possible to do as such depends on how jupyter cells work in vscode.

Veykril avatar Nov 29 '23 09:11 Veykril

Oops, I misspoke earlier when I said the semicolon-free statements could appear anywhere. They can only appear as the final statement in a cell.

That seems to work, thanks @Veykril! I'll run with this and report back if any other problems come up...

thomasjm avatar Nov 29 '23 11:11 thomasjm

Since the previous related issue that was linked above (3+ years ago), evcxr now uses rust-analyzer internally in order to figure out variables types, provide autocomplete and probably some other things I've forgotten.

I think in order to wrap the code in a way that would work consistently with what evcxr is doing, you'd probably need to actually call into evcxr. There's quite a bit of complexity in turning the code that the user supplies into the code that's given to rustc or rust-analyzer. For example, if you've already run some notebook cells, then there might be variables defined. Those variables need to still be defined in later cells and have their correct types.

But I have no idea how you would cleanly call into evcxr to get the wrapped code to analyze. Even if you could get the wrapped code, you still need to do the reverse - e.g. when an error is reported in the wrapped code, the span information needs to be mapped back to the original code. Evcxr does this internally, but I'm not sure how it would be done externally.

If you use Evcxr from a Jupyter Notebook in a web browser, then tab completion works and you also get red and yellow squigglies with hovers for errors and warnings. It's not everything that you would get editing regular rust code in vscode with rust-analyzer, but it's something.

I suspect if you want nice rust-analyzer based vscode evcxr integration, the best path is perhaps to write/edit/extend a vscode extension that calls through to the evcxr jupyter kernel, then leverage the copy of rust-analyzer built into evcxr to get whatever info you need. I'm not at all familiar with the state of Jupyter integration in vscode, so I don't know whether it would be best to extend an existing Jupyter Notebook extension or build something more from scratch.

davidlattimore avatar Nov 29 '23 11:11 davidlattimore

I would like to know the current situation of supporting, and there is any progress?

XRTIDE avatar Feb 26 '24 09:02 XRTIDE

There are no plans to implement this from our side in the foreseeable future if at all.

Veykril avatar Feb 26 '24 10:02 Veykril