Giter Site home page Giter Site logo

rls's Introduction

⚠️ RLS is no longer supported

RLS has been deprecated and is no longer supported. It has been replaced with rust-analyzer. Users are encouraged to uninstall RLS and follow the instructions in the rust-analyzer manual to install it for your editor.


Rust Language Server (RLS)

The RLS provides a server that runs in the background, providing IDEs, editors, and other tools with information about Rust programs. It supports functionality such as 'goto definition', symbol search, reformatting, and code completion, and enables renaming and refactorings.

A high-level overview of the architecture can be found here.

The RLS gets its source data from the compiler and from Racer. Where possible it uses data from the compiler which is precise and complete. Where it is not possible, (for example for code completion and where building is too slow), it uses Racer.

Since the Rust compiler does not yet support end-to-end incremental compilation, we can't offer a perfect experience. However, by optimising our use of the compiler and falling back to Racer, we can offer a pretty good experience for small to medium sized crates. As the RLS and compiler evolve, we'll offer a better experience for larger and larger crates.

The RLS is designed to be frontend-independent. We hope it will be widely adopted by different editors and IDEs. To seed development, we provide a reference implementation of an RLS frontend for Visual Studio Code.

Setup

Step 1: Install rustup

You can install rustup on many platforms. This will help us quickly install the RLS and its dependencies.

If you already have rustup installed, update to ensure you have the latest rustup and compiler:

rustup update

If you're going to use the VSCode extension, you can skip step 2.

Step 2: Install the RLS

Once you have rustup installed, run the following commands:

rustup component add rls rust-analysis rust-src

error: component 'rls' is unavailable for download (nightly)

The development of rustc's internals is quite fast paced. Downstream projects that rely on nightly internals, particularly clippy, can break fairly often because of this.

When such breakages occur the nightly release will be missing rls. This is a trade-off compared with the other option of just not publishing the night's release, but does avoid blocking the rust nightly releases for people that don't need clippy/rls.

To mitigate the issues we have:

  • rustup will warn if the update is missing any components you currently have. This means you can no longer accidentally update to a no-rls release. Once rls is available again it'll update.
  • rls, clippy are available on the stable channel. Meaning most developers installing for the first time should use stable.
  • However, if you need latest nightly rls you can use https://rust-lang.github.io/rustup-components-history/ to find and install a dated nightly release ie rustup install nightly-2018-12-06.

Also see #641.

Running

The RLS is built to work with many IDEs and editors, we mostly use VSCode to test the RLS. The easiest way is to use the published extension.

You'll know it's working when you see this in the status bar at the bottom, with a spinning indicator:

RLS: working ◐

Once you see:

RLS

Then you have the full set of capabilities available to you. You can goto def, find all refs, rename, goto type, etc. Completions are also available using the heuristics that Racer provides. As you type, your code will be checked and error squiggles will be reported when errors occur. You can hover these squiggles to see the text of the error.

Configuration

The RLS can be configured on a per-project basis; using the Visual Studio Code extension this will be done via the workspace settings file settings.json.

Other editors will have their own way of sending the workspace/DidChangeConfiguration method. Options are nested in the rust object, so your LSP client might send {"settings":{"rust":{"unstable_features":true}}} as parameters.

Entries in this file will affect how the RLS operates and how it builds your project.

Currently we accept the following options:

  • unstable_features (bool, defaults to false) enables unstable features. Currently no option requires this flag.
  • sysroot (String, defaults to "") if the given string is not empty, use the given path as the sysroot for all rustc invocations instead of trying to detect the sysroot automatically
  • target (String, defaults to "") if the given string is not empty, use the given target triple for all rustc invocations
  • wait_to_build (u64) overrides build debounce duration (ms). This is otherwise automatically inferred by the latest build duration.
  • all_targets (bool, defaults to true) checks the project as if you were running cargo check --all-targets. I.e., check all targets and integration tests too
  • crate_blacklist ([String], defaults to this list) allows to specify which crates should be skipped by the RLS. By default skips libraries that are of considerable size but which the user often may not be directly interested in, thus reducing the build latency.
  • build_on_save (bool, defaults to false) toggles whether the RLS should perform continuous analysis or only after a file is saved
  • features ([String], defaults to empty) list of Cargo features to enable
  • all_features (bool, defaults to false) enables all Cargo features
  • no_default_features (bool, defaults to false) disables default Cargo features
  • racer_completion (bool, defaults to true) enables code completion using racer (which is, at the moment, our only code completion backend). Also enables hover tooltips & go-to-definition to fall back to racer when save-analysis data is unavailable.
  • clippy_preference (String, defaults to "opt-in") controls eagerness of clippy diagnostics when available. Valid values are (case-insensitive):
    • "off" Disable clippy lints.
    • "on" Display the same diagnostics as command-line clippy invoked with no arguments (clippy::all unless overridden).
    • "opt-in" Only display the lints explicitly enabled in the code. Start by adding #![warn(clippy::all)] to the root of each crate you want linted.

and the following unstable options:

  • build_lib (bool, defaults to false) checks the project as if you passed the --lib argument to cargo. Mutually exclusive with, and preferred over, build_bin.
  • build_bin (String, defaults to "") checks the project as if you passed -- bin <build_bin> argument to cargo. Mutually exclusive with build_lib.
  • cfg_test (bool, defaults to false) checks the project as if you were running cargo test rather than cargo build. I.e., compiles (but does not run) test code.
  • full_docs (bool, defaults to false) instructs rustc to populate the save-analysis data with full source documentation. When set to false, only the first paragraph is recorded. This option currently has little to no effect on hover tooltips. The save-analysis docs are only used if source extraction fails. This option has no effect on the standard library.
  • show_hover_context (bool, defaults to true) show additional context in hover tooltips when available. This is often the local variable declaration. When set to false the content is only available when holding the ctrl key in some editors.

Troubleshooting

For tips on debugging and troubleshooting, see debugging.md.

Contributing

You can look in the contributing.md in this repo to learn more about contributing to this project.

If you want to implement RLS support in an editor, see clients.md.

rls's People

Contributors

alexcrichton avatar alexheretic avatar aloucks avatar bors avatar bors-voyager[bot] avatar bvinc avatar calebcartwright avatar dependabot-support avatar doriath avatar eddyb avatar ehuss avatar fitzgen avatar frewsxcv avatar h-michael avatar jabagawee avatar johshoff avatar jonasbb avatar kngwyu avatar kogai avatar lijinpei avatar mark-simulacrum avatar mati865 avatar matklad avatar matthiaskrgr avatar nrc avatar oli-obk avatar sebastiencs avatar spacekookie avatar tetsuharuohzeki avatar xanewok avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rls's Issues

Support another editor

Should be non-LS protocol based. My vote is for Sublime, but could also try Atom, Vim, or Emacs.

Necessary to ensure the RLS is editor-independent.

compiler crashes when making edits

When making edits to the code, the compiler will sometimes get into a bad state.

One example crash:

note: run with `RUST_BACKTRACE=1` for a backtrace

thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:323
stack backtrace:
   1:        0x10608efe8 - std::sys::backtrace::tracing::imp::write::he09d58d1497100a9
   2:        0x106096faf - std::panicking::default_hook::{{closure}}::hf3f7aa526824ae88
   3:        0x1060952e5 - std::panicking::default_hook::h691f7ee16f920a74
   4:        0x106095a06 - std::panicking::rust_panic_with_hook::haa794968064098e8
   5:        0x1060958a4 - std::panicking::begin_panic::h78b83f343fc429be
   6:        0x1060957c2 - std::panicking::begin_panic_fmt::h8b3207332f403a68
   7:        0x106095727 - rust_begin_unwind
   8:        0x1060c3af0 - core::panicking::panic_fmt::h5cca666ac160c125
   9:        0x1060c39f4 - core::panicking::panic::h30a00c8dd89101b4
  10:        0x10471f109 - <rustc_save_analysis::dump_visitor::DumpVisitor<'l, 'tcx, 'll, D> as syntax::visit::Visitor>::visit_expr::h163cde99c278fc43
  11:        0x1046f10ce - <rustc_save_analysis::dump_visitor::DumpVisitor<'l, 'tcx, 'll, D>>::process_method::h04468bf911ce2542
  12:        0x104701439 - <rustc_save_analysis::dump_visitor::DumpVisitor<'l, 'tcx, 'll, D>>::process_impl_item::h4e762d98295a5e48
  13:        0x104705074 - <rustc_save_analysis::dump_visitor::DumpVisitor<'l, 'tcx, 'll, D> as syntax::visit::Visitor>::visit_item::h02ded85bb6033cf8
  14:        0x1047327aa - rustc_save_analysis::process_crate::he5e07bdf3c6cb726
  15:        0x103bed73b - <rustc_driver::RustcDefaultCalls as rustc_driver::CompilerCalls<'a>>::build_controller::{{closure}}::{{closure}}::hbf39625416cfff33
  16:        0x103bf2071 - <rustc_driver::RustcDefaultCalls as rustc_driver::CompilerCalls<'a>>::build_controller::{{closure}}::h858ba59f1e3b27b9
  17:        0x103bee6df - rustc_driver::driver::compile_input::{{closure}}::h273cad8b7f8d1024
  18:        0x103be7813 - rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::h7ce10fd09281598f
  19:        0x103bb5036 - rustc_driver::driver::phase_3_run_analysis_passes::he8ee46117275842d
  20:        0x103ba2f9a - rustc_driver::driver::compile_input::h0271fc4a3333b327
  21:        0x103bc98e9 - rustc_driver::run_compiler::h1315ba568dec0ab8
  22:        0x1036be10d - rls::build::BuildQueue::rustc::{{closure}}::{{closure}}::h66962e2240eaa638
  23:        0x1036bd8ca - rustc_driver::run::{{closure}}::h6946deb7d8e0395b
  24:        0x1036be2c3 - rustc_driver::monitor::{{closure}}::hd1ab9dd35d21c63f
  25:        0x10365457b - <std::panic::AssertUnwindSafe<F> as core::ops::FnOnce<()>>::call_once::ha448607329ef3916
  26:        0x1034bce26 - std::panicking::try::do_call::h4d4051ea56bb4a02
  27:        0x10609756a - __rust_maybe_catch_panic
  28:        0x1034bac10 - std::panicking::try::h8f6846036d1a2b63
  29:        0x1034ae735 - std::panic::catch_unwind::ha11e26ecdbf248e3
  30:        0x1036c32a1 - std::thread::Builder::spawn::{{closure}}::h6b4547929665b7b8
  31:        0x1035208a0 - <F as alloc::boxed::FnBox<A>>::call_box::h7d5e87dbc610ebb6
  32:        0x106094a54 - std::sys::thread::Thread::new::thread_start::h2d239c26e84b740e
  33:     0x7fff9a8bdaba - _pthread_body
  34:     0x7fff9a8bda06 - _pthread_start

Starting RLS with unsaved changes causes carnage with http protocol

This doesn't need to block the alpha release if it is not a problem when using the LS protocol (#14).

An actual fix (if necessary) could be that the RLS starts in an uninit state and any message received returns an uninit reply in that state. If a plugin gets such a message, it must send an init message which contains the project state, then resend the original message.

Cannot open file on Windows

I'm testing VS Code extension on Windows - I cannot get anything to work at the moment, but the following keeps getting printed on the stderr:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value:
Io(Some("/d%3A/Documents/rustls/src/server.rs"), Some("Could not open file: /d%3A/Documents/rustls/src/server.rs"))',
../src/libcore\result.rs

Looks like the path is URL encoded, maybe that's causing issues?

Sharing the language-server-protocol types

In conjunction to releasing a new version of https://github.com/gluon-lang/gluon_language-server I was planning to also release a crate containing only the types used to communicate in the language-server-protocol https://github.com/Marwes/gluon_language-server/tree/source_map/vscode-languageserver-types.

I believe that at least for just these types there is little reason for duplicating the implementation effort (especially since there seems to be some inconsistencies in the protocol microsoft/language-server-protocol#87). Is there any interest in using that crate (or a crate like it) here as well? I'd be happy to move it to a separate repository as well if that seems easier to work with.

cc @bruno-medeiros

Related #35

LSP support

@jonathandturner I was pointed to the lsp_support branch by @nrc , and I was wondering how far/mature that work is? I've been working on LSP implementation for Rust (https://github.com/RustDT/RustLSP), and I was wondering if this could be of use for RustLS? (RustLSP is meant to be independent of the actual language the server engine is made for)

RustLSP is still in early stages too, but I'm planning to make it more complete and robust.

Skip borrow checking

Not sure if this is worth doing, but could make a difference on larger projects.

Documentation

  • README.md - how to build and run
  • how to use with std libs
  • architecture overview

other things?

Report the source of information over the LS protocol

For 'goto def' (and in the future, completions) information could come from either the compiler or Racer, we used to report this in the http setup and it would be nice to do the same for the LS setup, for debugging purposes.

Virtual File System

High level goal

Keep a copy of the files in a project in memory, when the IDE reports a change, track that in the VFS rather than forcing a save. Run the compiler on the VFS rather than the files on disk. This saves the annoying forced saves, plus could be faster since the compiler might be able to avoid disk IO.

Details

There are several possible approaches:

Compiler maintains VFS

This requires having a long-running compiler. The RLS just passes on changes to the compiler (across IPC, probably) which updates its VFS and when we ask for a compile it converts the VFS into a CodeMap and starts compiling,

RLS maintains VFS

Either we build the compiler in process and call it with the VFS, or we run the compiler out of process and keep the VFS in shmem. The former means distributing (and building) the compiler with the RLS. The latter means adding shmem facilities to the compiler plus handling locking etc. on the RLS side. I prefer the former, but it makes the RLS a much less lightweight option for users.

Short-term hacks

We could keep a shadow file system on disk which the RLS keeps up to date, then run the compiler on that. This loses the performance advantage but does avoid the forced saving in the IDE.

We could track changes rather than the whole project and pass the changes to the compiler via stdin or some other ipc mechanism. Again, we don't get the performance wins of avoiding disk IO, but we avoid saving. Also avoids having a big temporary file system. Would require some changes to the compiler (more than we would like since the codemap is basically immutable).

Note that in the short-term (at least until incremental compilation) it is not too important to avoid the disk IO, since it is overwhelmed by build times, time-wise.

Better Rustfmt integration

RLS currently supports rudimentary Rustfmt integration. It could be improved a lot:

  • currently errors if any sub-modules are present and the file is not saved to disk (rust-lang/rustfmt#562)
  • we currently return the entire re-formatted file, it would be better to return the ranges modified and the new text (and also update the VFS with that) (blocked on rust-lang/rustfmt#1173)
  • If there are no changes, don't change anything (#334). Rustfmt sort of has the facility to tell us this, but it is not exposed in the mode we need. Could be fixed by the diff approach, but might be easier to add as step towards that.
  • allow formatting line ranges (#333) (VSCode has a provider for this, but blocked on rust-lang/rustfmt#1159)
  • add a format-on-save option (apparently this should Just Work, need to document)
  • take the indent-width hint from VSCode and pass it to Rustfmt (but don't override the user's setting, if set in rustfmt.toml)
  • use the user's rustfmt.toml (#331)
  • Formatting adds newline at the end on file on each format (#282)
  • Formatting seems to be broken? (#242)

highlight on hover for LS protocol

This worked on http proto using find all refs, we presumably just need to use the existing info to fill out the right LS request.

Happy to mentor this if someone wants to have a go.

VS Code plugin still saves on '.'

I put in a hack for the demo to always save on the '.' key so that completions would work well. We'll need to pull this out when we do the VFS transition

Proper logging

Logging writes sometimes to stderr and sometimes to a hard-coded file. There is no log levels. We should use liblog and do this properly.

refactoring: factor out a general notify method

The Output trait has a notify method, but it assumes no data, we should have a general version that does allow data (success could be a model, though I don't like the fact that it takes a string as an arg). We would use this in at least ActionHandler::Build.

Compiler backed code completion

Can do non-dot completion using a map of scopes to idents. Completion after the dot is harder, but we may be able to pre-compute lists of idents and try to stay ahead of the programmer as they type.

Feature Request: Explain language feature

As you probably know from the State of Rust survey 2016 "1 in 4 people commented on the learning curve when talking about Rust’s challenges". I'd like to propose a small feature which could be helpful for beginners.

The LS protocol already contains features "Goto Definition Request", "Document Highlights Request" and stuff like that which help to navigate and understand the actual code itself. As I heard that the LS protocol is extensible I thought that it could be extended to help to understand the language, too.

A small non-Rust example I experienced some days before. I tried to explain a non-JavaScript (actually TypeScript) developer some new ES2105 code. He struggled at a line like that:

abstract async self (): Promise<void>;

Even with syntax highlighting enabled he had a hard time to understand that self was the name of a function and not a keyword from JavaScript (like async) or TypeScript (like abstract). He didn't trust the syntax highlighting. If you'd have been alone (so he couldn't asked), it'd have been really helpful for him, if he could have a feature like "Explain this language feature" inside his IDE which could have told him something like: 'self' is the name of a function. It is a method of classFoo... and so on.

Some years ago I saw an interactive app which did the same for CSS (if I remember correctly). Sadly I can't find it anymore. It worked like that:

.foo {
  color: red;
}

If you hovered above .foo it would tell something like: '.foo' is a class selector.. If you hovered above color it would tell something like: 'color' is a property inside a style rule.. If you hovered above red it would tell something like: 'red' is the value assigned to the 'color' property. and so on.

From my own experience when I started learning Rust I had a hard time to figure out how to spell &str so I can search for it more easily. It would have been nice if I could have asked my editor on any occurence of &str in my code "Explain me this language feature" and if it would have returned something like that.

The str type, also called a 'string slice', is the most primitive string type. It is usually seen in its borrowed form, &str. It is also the type of string literals, &'static str.

Strings slices are always valid UTF-8.

[Read more](https://doc.rust-lang.org/beta/std/primitive.str.html)

I'd have immediately learned "Oh, this is called a string slice."

I'd guess this could be turned into a powerful feature.

Don't serialise error data

We are running the compiler in-process, so we should just pass the data, rather than serialising it to JSON and then back again.

files get out of sync with racer

We noticed this before when putting the demo together, and my hack of "save when hitting a dot" seemed to fix it.

Currently, when you hit dot, you'll sometimes get the correct list of members and sometimes get a list of other identifiers. We've seen this before when racer gets out of sync with the current state of the buffer.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.