aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/adt.rs1
-rw-r--r--crates/ra_hir_def/src/body/lower.rs38
-rw-r--r--crates/ra_hir_def/src/expr.rs2
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs46
-rw-r--r--crates/ra_ide/src/references/rename.rs106
-rw-r--r--crates/ra_mbe/src/subtree_source.rs5
-rw-r--r--crates/ra_mbe/src/tests.rs22
-rw-r--r--docs/user/features.md30
-rw-r--r--docs/user/readme.adoc19
10 files changed, 238 insertions, 35 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 985f409e8..2bdfc2b8d 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -174,6 +174,7 @@ impl HasChildSource for VariantId {
174 } 174 }
175} 175}
176 176
177#[derive(Debug, Copy, Clone, PartialEq, Eq)]
177pub enum StructKind { 178pub enum StructKind {
178 Tuple, 179 Tuple,
179 Record, 180 Record,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index b1626fa11..b3fb6d452 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -15,6 +15,7 @@ use ra_syntax::{
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 adt::StructKind,
18 body::{Body, BodySourceMap, Expander, PatPtr}, 19 body::{Body, BodySourceMap, Expander, PatPtr},
19 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
20 db::DefDatabase, 21 db::DefDatabase,
@@ -22,11 +23,12 @@ use crate::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 23 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 24 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
24 }, 25 },
26 item_scope::BuiltinShadowMode,
25 path::GenericArgs, 27 path::GenericArgs,
26 path::Path, 28 path::Path,
27 type_ref::{Mutability, TypeRef}, 29 type_ref::{Mutability, TypeRef},
28 ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc, 30 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
29 StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 31 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
30}; 32};
31 33
32pub(super) fn lower( 34pub(super) fn lower(
@@ -571,7 +573,37 @@ where
571 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 573 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
572 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); 574 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
573 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); 575 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
574 Pat::Bind { name, mode: annotation, subpat } 576 if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
577 // This could also be a single-segment path pattern. To
578 // decide that, we need to try resolving the name.
579 let (resolved, _) = self.expander.crate_def_map.resolve_path(
580 self.db,
581 self.expander.module.local_id,
582 &name.clone().into(),
583 BuiltinShadowMode::Other,
584 );
585 match resolved.take_values() {
586 Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
587 Some(ModuleDefId::EnumVariantId(_)) => {
588 // this is only really valid for unit variants, but
589 // shadowing other enum variants with a pattern is
590 // an error anyway
591 Pat::Path(name.into())
592 }
593 Some(ModuleDefId::AdtId(AdtId::StructId(s)))
594 if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
595 {
596 // Funnily enough, record structs *can* be shadowed
597 // by pattern bindings (but unit or tuple structs
598 // can't).
599 Pat::Path(name.into())
600 }
601 // shadowing statics is an error as well, so we just ignore that case here
602 _ => Pat::Bind { name, mode: annotation, subpat },
603 }
604 } else {
605 Pat::Bind { name, mode: annotation, subpat }
606 }
575 } 607 }
576 ast::Pat::TupleStructPat(p) => { 608 ast::Pat::TupleStructPat(p) => {
577 let path = p.path().and_then(|path| self.expander.parse_path(path)); 609 let path = p.path().and_then(|path| self.expander.parse_path(path));
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 9707c5527..66d004717 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -48,7 +48,7 @@ pub enum Literal {
48 48
49#[derive(Debug, Clone, Eq, PartialEq)] 49#[derive(Debug, Clone, Eq, PartialEq)]
50pub enum Expr { 50pub enum Expr {
51 /// This is produced if syntax tree does not have a required expression piece. 51 /// This is produced if the syntax tree does not have a required expression piece.
52 Missing, 52 Missing,
53 Path(Path), 53 Path(Path),
54 If { 54 If {
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index a495ecbfe..bf8ea192b 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -189,7 +189,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
189 }; 189 };
190 // use a new type variable if we got Ty::Unknown here 190 // use a new type variable if we got Ty::Unknown here
191 let ty = self.insert_type_vars_shallow(ty); 191 let ty = self.insert_type_vars_shallow(ty);
192 self.unify(&ty, expected); 192 if !self.unify(&ty, expected) {
193 // FIXME record mismatch, we need to change the type of self.type_mismatches for that
194 }
193 let ty = self.resolve_ty_as_possible(ty); 195 let ty = self.resolve_ty_as_possible(ty);
194 self.write_pat_ty(pat, ty.clone()); 196 self.write_pat_ty(pat, ty.clone());
195 ty 197 ty
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index e25d6dbc4..81d00c2af 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -1,4 +1,4 @@
1use super::infer; 1use super::{infer, infer_with_mismatches};
2use insta::assert_snapshot; 2use insta::assert_snapshot;
3use test_utils::covers; 3use test_utils::covers;
4 4
@@ -236,3 +236,47 @@ fn test(a1: A<u32>, o: Option<u64>) {
236 "### 236 "###
237 ); 237 );
238} 238}
239
240#[test]
241fn infer_const_pattern() {
242 assert_snapshot!(
243 infer_with_mismatches(r#"
244enum Option<T> { None }
245use Option::None;
246struct Foo;
247const Bar: usize = 1;
248
249fn test() {
250 let a: Option<u32> = None;
251 let b: Option<i64> = match a {
252 None => None,
253 };
254 let _: () = match () { Foo => Foo }; // Expected mismatch
255 let _: () = match () { Bar => Bar }; // Expected mismatch
256}
257"#, true),
258 @r###"
259 [74; 75) '1': usize
260 [88; 310) '{ ...atch }': ()
261 [98; 99) 'a': Option<u32>
262 [115; 119) 'None': Option<u32>
263 [129; 130) 'b': Option<i64>
264 [146; 183) 'match ... }': Option<i64>
265 [152; 153) 'a': Option<u32>
266 [164; 168) 'None': Option<u32>
267 [172; 176) 'None': Option<i64>
268 [193; 194) '_': ()
269 [201; 224) 'match ... Foo }': Foo
270 [207; 209) '()': ()
271 [212; 215) 'Foo': Foo
272 [219; 222) 'Foo': Foo
273 [255; 256) '_': ()
274 [263; 286) 'match ... Bar }': usize
275 [269; 271) '()': ()
276 [274; 277) 'Bar': usize
277 [281; 284) 'Bar': usize
278 [201; 224): expected (), got Foo
279 [263; 286): expected (), got usize
280 "###
281 );
282}
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index c46b78cb6..bdb90020b 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -98,6 +98,17 @@ fn rename_mod(
98 }; 98 };
99 source_file_edits.push(edit); 99 source_file_edits.push(edit);
100 100
101 if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(db, position, None) {
102 let ref_edits = refs.references.into_iter().map(|reference| {
103 source_edit_from_file_id_range(
104 reference.file_range.file_id,
105 reference.file_range.range,
106 new_name,
107 )
108 });
109 source_file_edits.extend(ref_edits);
110 }
111
101 Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits)) 112 Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits))
102} 113}
103 114
@@ -383,6 +394,101 @@ mod tests {
383 ); 394 );
384 } 395 }
385 396
397 #[test]
398 fn test_module_rename_in_path() {
399 test_rename(
400 r#"
401 mod <|>foo {
402 pub fn bar() {}
403 }
404
405 fn main() {
406 foo::bar();
407 }"#,
408 "baz",
409 r#"
410 mod baz {
411 pub fn bar() {}
412 }
413
414 fn main() {
415 baz::bar();
416 }"#,
417 );
418 }
419
420 #[test]
421 fn test_rename_mod_filename_and_path() {
422 let (analysis, position) = analysis_and_position(
423 "
424 //- /lib.rs
425 mod bar;
426 fn f() {
427 bar::foo::fun()
428 }
429
430 //- /bar.rs
431 pub mod foo<|>;
432
433 //- /bar/foo.rs
434 // pub fn fun() {}
435 ",
436 );
437 let new_name = "foo2";
438 let source_change = analysis.rename(position, new_name).unwrap();
439 assert_debug_snapshot!(&source_change,
440@r###"
441 Some(
442 RangeInfo {
443 range: [8; 11),
444 info: SourceChange {
445 label: "rename",
446 source_file_edits: [
447 SourceFileEdit {
448 file_id: FileId(
449 2,
450 ),
451 edit: TextEdit {
452 atoms: [
453 AtomTextEdit {
454 delete: [8; 11),
455 insert: "foo2",
456 },
457 ],
458 },
459 },
460 SourceFileEdit {
461 file_id: FileId(
462 1,
463 ),
464 edit: TextEdit {
465 atoms: [
466 AtomTextEdit {
467 delete: [27; 30),
468 insert: "foo2",
469 },
470 ],
471 },
472 },
473 ],
474 file_system_edits: [
475 MoveFile {
476 src: FileId(
477 3,
478 ),
479 dst_source_root: SourceRootId(
480 0,
481 ),
482 dst_path: "bar/foo2.rs",
483 },
484 ],
485 cursor_position: None,
486 },
487 },
488 )
489 "###);
490 }
491
386 fn test_rename(text: &str, new_name: &str, expected: &str) { 492 fn test_rename(text: &str, new_name: &str, expected: &str) {
387 let (analysis, position) = single_file_with_position(text); 493 let (analysis, position) = single_file_with_position(text);
388 let source_change = analysis.rename(position, new_name).unwrap(); 494 let source_change = analysis.rename(position, new_name).unwrap();
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index dacca8279..91e324db9 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_parser::{Token, TokenSource}; 3use ra_parser::{Token, TokenSource};
4use ra_syntax::{lex_single_valid_syntax_kind, SmolStr, SyntaxKind, SyntaxKind::*, T}; 4use ra_syntax::{lex_single_syntax_kind, SmolStr, SyntaxKind, SyntaxKind::*, T};
5use std::cell::{Cell, Ref, RefCell}; 5use std::cell::{Cell, Ref, RefCell};
6use tt::buffer::{Cursor, TokenBuffer}; 6use tt::buffer::{Cursor, TokenBuffer};
7 7
@@ -129,7 +129,8 @@ fn convert_delim(d: Option<tt::DelimiterKind>, closing: bool) -> TtToken {
129} 129}
130 130
131fn convert_literal(l: &tt::Literal) -> TtToken { 131fn convert_literal(l: &tt::Literal) -> TtToken {
132 let kind = lex_single_valid_syntax_kind(&l.text) 132 let kind = lex_single_syntax_kind(&l.text)
133 .map(|(kind, _error)| kind)
133 .filter(|kind| kind.is_literal()) 134 .filter(|kind| kind.is_literal())
134 .unwrap_or_else(|| match l.text.as_ref() { 135 .unwrap_or_else(|| match l.text.as_ref() {
135 "true" => T![true], 136 "true" => T![true],
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index e0d689704..cb228702f 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1374,14 +1374,22 @@ pub(crate) struct MacroFixture {
1374 1374
1375impl MacroFixture { 1375impl MacroFixture {
1376 pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree { 1376 pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree {
1377 let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); 1377 self.try_expand_tt(invocation).unwrap()
1378 }
1379
1380 fn try_expand_tt(&self, invocation: &str) -> Result<tt::Subtree, ExpandError> {
1381 let source_file = ast::SourceFile::parse(invocation).tree();
1378 let macro_invocation = 1382 let macro_invocation =
1379 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 1383 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1380 1384
1381 let (invocation_tt, _) = 1385 let (invocation_tt, _) =
1382 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 1386 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
1383 1387
1384 self.rules.expand(&invocation_tt).unwrap() 1388 self.rules.expand(&invocation_tt)
1389 }
1390
1391 fn assert_expand_err(&self, invocation: &str, err: &ExpandError) {
1392 assert_eq!(self.try_expand_tt(invocation).as_ref(), Err(err));
1385 } 1393 }
1386 1394
1387 fn expand_items(&self, invocation: &str) -> SyntaxNode { 1395 fn expand_items(&self, invocation: &str) -> SyntaxNode {
@@ -1539,3 +1547,13 @@ fn test_repeat_bad_var() {
1539 ) 1547 )
1540 .assert_expand_items("foo!(b0 b1);", "b0 b1"); 1548 .assert_expand_items("foo!(b0 b1);", "b0 b1");
1541} 1549}
1550
1551#[test]
1552fn test_expand_bad_literal() {
1553 parse_macro(
1554 r#"
1555 macro_rules! foo { ($i:literal) => {}; }
1556 "#,
1557 )
1558 .assert_expand_err(r#"foo!(&k");"#, &ExpandError::NoMatchingRule);
1559}
diff --git a/docs/user/features.md b/docs/user/features.md
index a00fa35da..f705e5115 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -1,10 +1,10 @@
1This documents is an index of features that rust-analyzer language server 1This document is an index of features that the rust-analyzer language server
2provides. Shortcuts are for the default VS Code layout. If there's no shortcut, 2provides. Shortcuts are for the default VS Code layout. If there's no shortcut,
3you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action. 3you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
4 4
5### Workspace Symbol <kbd>ctrl+t</kbd> 5### Workspace Symbol <kbd>ctrl+t</kbd>
6 6
7Uses fuzzy-search to find types, modules and function by name across your 7Uses fuzzy-search to find types, modules and functions by name across your
8project and dependencies. This is **the** most useful feature, which improves code 8project and dependencies. This is **the** most useful feature, which improves code
9navigation tremendously. It mostly works on top of the built-in LSP 9navigation tremendously. It mostly works on top of the built-in LSP
10functionality, however `#` and `*` symbols can be used to narrow down the 10functionality, however `#` and `*` symbols can be used to narrow down the
@@ -13,7 +13,7 @@ search. Specifically,
13- `Foo` searches for `Foo` type in the current workspace 13- `Foo` searches for `Foo` type in the current workspace
14- `foo#` searches for `foo` function in the current workspace 14- `foo#` searches for `foo` function in the current workspace
15- `Foo*` searches for `Foo` type among dependencies, including `stdlib` 15- `Foo*` searches for `Foo` type among dependencies, including `stdlib`
16- `foo#*` searches for `foo` function among dependencies. 16- `foo#*` searches for `foo` function among dependencies
17 17
18That is, `#` switches from "types" to all symbols, `*` switches from the current 18That is, `#` switches from "types" to all symbols, `*` switches from the current
19workspace to dependencies. 19workspace to dependencies.
@@ -30,7 +30,7 @@ Provides a tree of the symbols defined in the file. Can be used to
30 30
31Some features trigger on typing certain characters: 31Some features trigger on typing certain characters:
32 32
33- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression. 33- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
34- Enter inside comments automatically inserts `///` 34- Enter inside comments automatically inserts `///`
35- typing `.` in a chain method call auto-indents 35- typing `.` in a chain method call auto-indents
36 36
@@ -58,7 +58,7 @@ Navigates to the type of an identifier.
58 58
59#### Run 59#### Run
60 60
61Shows popup suggesting to run a test/benchmark/binary **at the current cursor 61Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
62location**. Super useful for repeatedly running just a single test. Do bind this 62location**. Super useful for repeatedly running just a single test. Do bind this
63to a shortcut! 63to a shortcut!
64 64
@@ -87,15 +87,15 @@ Shows the full macro expansion of the macro at current cursor.
87 87
88#### Status 88#### Status
89 89
90Shows internal statistic about memory usage of rust-analyzer 90Shows internal statistic about memory usage of rust-analyzer.
91 91
92#### Show RA Version 92#### Show RA Version
93 93
94Show current rust-analyzer version 94Show current rust-analyzer version.
95 95
96#### Run garbage collection 96#### Run Garbage Collection
97 97
98Manually triggers GC 98Manually triggers GC.
99 99
100#### Start Cargo Watch 100#### Start Cargo Watch
101 101
@@ -103,7 +103,7 @@ Start `cargo watch` for live error highlighting. Will prompt to install if it's
103 103
104#### Stop Cargo Watch 104#### Stop Cargo Watch
105 105
106Stop `cargo watch` 106Stop `cargo watch`.
107 107
108### Assists (Code Actions) 108### Assists (Code Actions)
109 109
@@ -122,11 +122,11 @@ is placed at the appropriate position. Even though `if` is easy to type, you
122still want to complete it, to get ` { }` for free! `return` is inserted with a 122still want to complete it, to get ` { }` for free! `return` is inserted with a
123space or `;` depending on the return type of the function. 123space or `;` depending on the return type of the function.
124 124
125When completing a function call, `()` are automatically inserted. If function 125When completing a function call, `()` are automatically inserted. If a function
126takes arguments, cursor is positioned inside the parenthesis. 126takes arguments, the cursor is positioned inside the parenthesis.
127 127
128There are postifx completions, which can be triggerd by typing something like 128There are postifx completions, which can be triggerd by typing something like
129`foo().if`. The word after `.` determines postifx completion, possible variants are: 129`foo().if`. The word after `.` determines postifx completion. Possible variants are:
130 130
131- `expr.if` -> `if expr {}` 131- `expr.if` -> `if expr {}`
132- `expr.match` -> `match expr {}` 132- `expr.match` -> `match expr {}`
@@ -147,12 +147,12 @@ There also snippet completions:
147 147
148- `tfn` -> `#[test] fn f(){}` 148- `tfn` -> `#[test] fn f(){}`
149 149
150### Code highlighting 150### Code Highlighting
151 151
152Experimental feature to let rust-analyzer highlight Rust code instead of using the 152Experimental feature to let rust-analyzer highlight Rust code instead of using the
153default highlighter. 153default highlighter.
154 154
155#### Rainbow highlighting 155#### Rainbow Highlighting
156 156
157Experimental feature that, given code highlighting using rust-analyzer is 157Experimental feature that, given code highlighting using rust-analyzer is
158active, will pick unique colors for identifiers. 158active, will pick unique colors for identifiers.
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index 74fda0abe..f1386a8f9 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -6,10 +6,10 @@
6 6
7// Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository 7// Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository
8 8
9At it's core, rust-analyzer is a *library* for semantic analysis of the Rust code as it changes over time. 9At its core, rust-analyzer is a *library* for semantic analysis of Rust code as it changes over time.
10This manual focuses on a specific usage of the library -- the implementation of 10This manual focuses on a specific usage of the library -- the implementation of
11https://microsoft.github.io/language-server-protocol/[Language Server Protocol]. 11https://microsoft.github.io/language-server-protocol/[Language Server Protocol].
12LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic feature like completion or goto definition by talking to an external language server process. 12LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process.
13 13
14To improve this document, send a pull request against 14To improve this document, send a pull request against
15https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc[this file]. 15https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc[this file].
@@ -36,10 +36,9 @@ https://github.com/rust-analyzer/rust-analyzer/tree/master/editors/code[in tree]
36 36
37You can install the latest release of the plugin from 37You can install the latest release of the plugin from
38https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer[the marketplace]. 38https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer[the marketplace].
39By default, the plugin will download the matching version of the server as well. 39By default, the plugin will prompt you to download the matching version of the server as well:
40 40
41// FIXME: update the image (its text has changed) 41image::https://user-images.githubusercontent.com/9021944/75067008-17502500-54ba-11ea-835a-f92aac50e866.png[]
42image::https://user-images.githubusercontent.com/36276403/74103174-a40df100-4b52-11ea-81f4-372c70797924.png[]
43 42
44The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer`. 43The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer`.
45 44
@@ -60,7 +59,7 @@ $ cargo xtask install
60---- 59----
61 60
62You'll need Cargo, nodejs and npm for this. 61You'll need Cargo, nodejs and npm for this.
63To make VS Code use the freshly build server, add this to the settings: 62To make VS Code use the freshly built server, add this to the settings:
64 63
65[source,json] 64[source,json]
66---- 65----
@@ -72,7 +71,7 @@ Note that installing via `xtask install` does not work for VS Code Remote, inste
72=== Language Server Binary 71=== Language Server Binary
73 72
74Other editors generally require `rust-analyzer` binary to be in `$PATH`. 73Other editors generally require `rust-analyzer` binary to be in `$PATH`.
75You can download pre-build binary from 74You can download the pre-built binary from
76https://github.com/rust-analyzer/rust-analyzer/releases[releases] 75https://github.com/rust-analyzer/rust-analyzer/releases[releases]
77page, or you can install it from source using the following command: 76page, or you can install it from source using the following command:
78 77
@@ -85,7 +84,7 @@ $ cargo xtask install --server
85 84
86Emacs support is maintained https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[upstream]. 85Emacs support is maintained https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[upstream].
87 86
881. Install recent version of `emacs-lsp` package by following the instructions https://github.com/emacs-lsp/lsp-mode[here]. 871. Install the most recent version of `emacs-lsp` package by following the instructions https://github.com/emacs-lsp/lsp-mode[here].
892. Set `lsp-rust-server` to `'rust-analyzer`. 882. Set `lsp-rust-server` to `'rust-analyzer`.
903. Run `lsp` in a Rust buffer. 893. Run `lsp` in a Rust buffer.
914. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. 904. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
@@ -112,7 +111,7 @@ The are several LSP client implementations for vim:
112 https://github.com/autozimu/LanguageClient-neovim[here] 111 https://github.com/autozimu/LanguageClient-neovim[here]
113 * The github project wiki has extra tips on configuration 112 * The github project wiki has extra tips on configuration
114 113
1152. Configure by adding this to your vim/neovim config file (replacing the existing rust specific line if it exists): 1142. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists):
116+ 115+
117[source,vim] 116[source,vim]
118---- 117----
@@ -123,7 +122,7 @@ let g:LanguageClient_serverCommands = {
123 122
124==== nvim-lsp 123==== nvim-lsp
125 124
126NeoVim 0.5 (not yet released) has built in language server support. 125NeoVim 0.5 (not yet released) has built-in language server support.
127For a quick start configuration of rust-analyzer, use https://github.com/neovim/nvim-lsp#rust_analyzer[neovim/nvim-lsp]. 126For a quick start configuration of rust-analyzer, use https://github.com/neovim/nvim-lsp#rust_analyzer[neovim/nvim-lsp].
128Once `neovim/nvim-lsp` is installed, use `lua require'nvim_lsp'.rust_analyzer.setup({})` in your `init.vim`. 127Once `neovim/nvim-lsp` is installed, use `lua require'nvim_lsp'.rust_analyzer.setup({})` in your `init.vim`.
129 128