diff options
22 files changed, 233 insertions, 80 deletions
@@ -58,7 +58,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 | |||
58 | ## Quick Links | 58 | ## Quick Links |
59 | 59 | ||
60 | * API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide/ | 60 | * API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide/ |
61 | 61 | * Website: https://rust-analyzer.github.io/ | |
62 | 62 | ||
63 | ## License | 63 | ## License |
64 | 64 | ||
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index f81b4184a..ceffee9b8 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs | |||
@@ -582,8 +582,14 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { | |||
582 | hir::PathKind::Abs => ps.push("".into()), | 582 | hir::PathKind::Abs => ps.push("".into()), |
583 | hir::PathKind::Crate => ps.push("crate".into()), | 583 | hir::PathKind::Crate => ps.push("crate".into()), |
584 | hir::PathKind::Plain => {} | 584 | hir::PathKind::Plain => {} |
585 | hir::PathKind::Self_ => ps.push("self".into()), | 585 | hir::PathKind::Super(0) => ps.push("self".into()), |
586 | hir::PathKind::Super => ps.push("super".into()), | 586 | hir::PathKind::Super(lvl) => { |
587 | let mut chain = "super".to_string(); | ||
588 | for _ in 0..*lvl { | ||
589 | chain += "::super"; | ||
590 | } | ||
591 | ps.push(chain.into()); | ||
592 | } | ||
587 | hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, | 593 | hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, |
588 | } | 594 | } |
589 | ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); | 595 | ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 451b227a6..2e52a1f5c 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -58,6 +58,6 @@ pub use hir_def::{ | |||
58 | type_ref::Mutability, | 58 | type_ref::Mutability, |
59 | }; | 59 | }; |
60 | pub use hir_expand::{ | 60 | pub use hir_expand::{ |
61 | name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, | 61 | name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, |
62 | }; | 62 | }; |
63 | pub use hir_ty::{display::HirDisplay, CallableDef}; | 63 | pub use hir_ty::{display::HirDisplay, CallableDef}; |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 912a073ea..8bbf7ffa2 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -890,7 +890,7 @@ where | |||
890 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. | 890 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. |
891 | let mut path = mac.path.clone(); | 891 | let mut path = mac.path.clone(); |
892 | if path.is_ident() { | 892 | if path.is_ident() { |
893 | path.kind = PathKind::Self_; | 893 | path.kind = PathKind::Super(0); |
894 | } | 894 | } |
895 | 895 | ||
896 | self.def_collector.unexpanded_macros.push(MacroDirective { | 896 | self.def_collector.unexpanded_macros.push(MacroDirective { |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 4a249e7e7..1dbc4f371 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -10,6 +10,8 @@ | |||
10 | //! | 10 | //! |
11 | //! `ReachedFixedPoint` signals about this. | 11 | //! `ReachedFixedPoint` signals about this. |
12 | 12 | ||
13 | use std::iter::successors; | ||
14 | |||
13 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
14 | use ra_db::Edition; | 16 | use ra_db::Edition; |
15 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
@@ -97,9 +99,6 @@ impl CrateDefMap { | |||
97 | PathKind::Crate => { | 99 | PathKind::Crate => { |
98 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) | 100 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) |
99 | } | 101 | } |
100 | PathKind::Self_ => { | ||
101 | PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into()) | ||
102 | } | ||
103 | // plain import or absolute path in 2015: crate-relative with | 102 | // plain import or absolute path in 2015: crate-relative with |
104 | // fallback to extern prelude (with the simplification in | 103 | // fallback to extern prelude (with the simplification in |
105 | // rust-lang/rust#57745) | 104 | // rust-lang/rust#57745) |
@@ -123,9 +122,11 @@ impl CrateDefMap { | |||
123 | log::debug!("resolving {:?} in module", segment); | 122 | log::debug!("resolving {:?} in module", segment); |
124 | self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) | 123 | self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) |
125 | } | 124 | } |
126 | PathKind::Super => { | 125 | PathKind::Super(lvl) => { |
127 | if let Some(p) = self.modules[original_module].parent { | 126 | let m = successors(Some(original_module), |m| self.modules[*m].parent) |
128 | PerNs::types(ModuleId { krate: self.krate, local_id: p }.into()) | 127 | .nth(lvl as usize); |
128 | if let Some(local_id) = m { | ||
129 | PerNs::types(ModuleId { krate: self.krate, local_id }.into()) | ||
129 | } else { | 130 | } else { |
130 | log::debug!("super path in root module"); | 131 | log::debug!("super path in root module"); |
131 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 132 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); |
@@ -170,7 +171,7 @@ impl CrateDefMap { | |||
170 | if module.krate != self.krate { | 171 | if module.krate != self.krate { |
171 | let path = ModPath { | 172 | let path = ModPath { |
172 | segments: path.segments[i..].to_vec(), | 173 | segments: path.segments[i..].to_vec(), |
173 | kind: PathKind::Self_, | 174 | kind: PathKind::Super(0), |
174 | }; | 175 | }; |
175 | log::debug!("resolving {:?} in other crate", path); | 176 | log::debug!("resolving {:?} in other crate", path); |
176 | let defp_map = db.crate_def_map(module.krate); | 177 | let defp_map = db.crate_def_map(module.krate); |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 20d6d98ea..3b26e8337 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -56,7 +56,7 @@ impl ModPath { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | pub fn is_self(&self) -> bool { | 58 | pub fn is_self(&self) -> bool { |
59 | self.kind == PathKind::Self_ && self.segments.is_empty() | 59 | self.kind == PathKind::Super(0) && self.segments.is_empty() |
60 | } | 60 | } |
61 | 61 | ||
62 | /// If this path is a single identifier, like `foo`, return its name. | 62 | /// If this path is a single identifier, like `foo`, return its name. |
@@ -100,8 +100,7 @@ pub enum GenericArg { | |||
100 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 100 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
101 | pub enum PathKind { | 101 | pub enum PathKind { |
102 | Plain, | 102 | Plain, |
103 | Self_, | 103 | Super(u8), |
104 | Super, | ||
105 | Crate, | 104 | Crate, |
106 | // Absolute path | 105 | // Absolute path |
107 | Abs, | 106 | Abs, |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index a2e995198..c71b52d89 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -95,11 +95,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
95 | break; | 95 | break; |
96 | } | 96 | } |
97 | ast::PathSegmentKind::SelfKw => { | 97 | ast::PathSegmentKind::SelfKw => { |
98 | kind = PathKind::Self_; | 98 | kind = PathKind::Super(0); |
99 | break; | 99 | break; |
100 | } | 100 | } |
101 | ast::PathSegmentKind::SuperKw => { | 101 | ast::PathSegmentKind::SuperKw => { |
102 | kind = PathKind::Super; | 102 | kind = PathKind::Super(1); |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | } | 105 | } |
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index ea3fdb56c..062c02063 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs | |||
@@ -95,13 +95,13 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> | |||
95 | if prefix.is_some() { | 95 | if prefix.is_some() { |
96 | return None; | 96 | return None; |
97 | } | 97 | } |
98 | ModPath::from_simple_segments(PathKind::Self_, iter::empty()) | 98 | ModPath::from_simple_segments(PathKind::Super(0), iter::empty()) |
99 | } | 99 | } |
100 | ast::PathSegmentKind::SuperKw => { | 100 | ast::PathSegmentKind::SuperKw => { |
101 | if prefix.is_some() { | 101 | if prefix.is_some() { |
102 | return None; | 102 | return None; |
103 | } | 103 | } |
104 | ModPath::from_simple_segments(PathKind::Super, iter::empty()) | 104 | ModPath::from_simple_segments(PathKind::Super(1), iter::empty()) |
105 | } | 105 | } |
106 | ast::PathSegmentKind::Type { .. } => { | 106 | ast::PathSegmentKind::Type { .. } => { |
107 | // not allowed in imports | 107 | // not allowed in imports |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 94e1e466a..cb4e1950b 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -214,7 +214,13 @@ pub struct ExpansionInfo { | |||
214 | exp_map: Arc<mbe::TokenMap>, | 214 | exp_map: Arc<mbe::TokenMap>, |
215 | } | 215 | } |
216 | 216 | ||
217 | pub use mbe::Origin; | ||
218 | |||
217 | impl ExpansionInfo { | 219 | impl ExpansionInfo { |
220 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { | ||
221 | Some(self.arg.with_value(self.arg.value.parent()?)) | ||
222 | } | ||
223 | |||
218 | pub fn map_token_down(&self, token: InFile<&SyntaxToken>) -> Option<InFile<SyntaxToken>> { | 224 | pub fn map_token_down(&self, token: InFile<&SyntaxToken>) -> Option<InFile<SyntaxToken>> { |
219 | assert_eq!(token.file_id, self.arg.file_id); | 225 | assert_eq!(token.file_id, self.arg.file_id); |
220 | let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; | 226 | let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; |
@@ -228,7 +234,10 @@ impl ExpansionInfo { | |||
228 | Some(self.expanded.with_value(token)) | 234 | Some(self.expanded.with_value(token)) |
229 | } | 235 | } |
230 | 236 | ||
231 | pub fn map_token_up(&self, token: InFile<&SyntaxToken>) -> Option<InFile<SyntaxToken>> { | 237 | pub fn map_token_up( |
238 | &self, | ||
239 | token: InFile<&SyntaxToken>, | ||
240 | ) -> Option<(InFile<SyntaxToken>, Origin)> { | ||
232 | let token_id = self.exp_map.token_by_range(token.value.text_range())?; | 241 | let token_id = self.exp_map.token_by_range(token.value.text_range())?; |
233 | 242 | ||
234 | let (token_id, origin) = self.macro_def.0.map_id_up(token_id); | 243 | let (token_id, origin) = self.macro_def.0.map_id_up(token_id); |
@@ -242,7 +251,7 @@ impl ExpansionInfo { | |||
242 | let range = token_map.range_by_token(token_id)?; | 251 | let range = token_map.range_by_token(token_id)?; |
243 | let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) | 252 | let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) |
244 | .into_token()?; | 253 | .into_token()?; |
245 | Some(tt.with_value(token)) | 254 | Some((tt.with_value(token), origin)) |
246 | } | 255 | } |
247 | } | 256 | } |
248 | 257 | ||
diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 661628ae4..7a22bb0a4 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs | |||
@@ -1,56 +1,66 @@ | |||
1 | //! Utilities to work with files, produced by macros. | 1 | //! Utilities to work with files, produced by macros. |
2 | use std::iter::successors; | 2 | use std::iter::successors; |
3 | 3 | ||
4 | use hir::InFile; | 4 | use hir::{InFile, Origin}; |
5 | use ra_db::FileId; | 5 | use ra_db::FileId; |
6 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; | 6 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; |
7 | 7 | ||
8 | use crate::{db::RootDatabase, FileRange}; | 8 | use crate::{db::RootDatabase, FileRange}; |
9 | 9 | ||
10 | pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { | 10 | pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { |
11 | let expansion = match node.file_id.expansion_info(db) { | 11 | if let Some((range, Origin::Call)) = original_range_and_origin(db, node) { |
12 | None => { | 12 | return range; |
13 | } | ||
14 | |||
15 | if let Some(expansion) = node.file_id.expansion_info(db) { | ||
16 | if let Some(call_node) = expansion.call_node() { | ||
13 | return FileRange { | 17 | return FileRange { |
14 | file_id: node.file_id.original_file(db), | 18 | file_id: call_node.file_id.original_file(db), |
15 | range: node.value.text_range(), | 19 | range: call_node.value.text_range(), |
16 | } | 20 | }; |
17 | } | 21 | } |
18 | Some(it) => it, | 22 | } |
19 | }; | 23 | |
24 | FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } | ||
25 | } | ||
26 | |||
27 | fn original_range_and_origin( | ||
28 | db: &RootDatabase, | ||
29 | node: InFile<&SyntaxNode>, | ||
30 | ) -> Option<(FileRange, Origin)> { | ||
31 | let expansion = node.file_id.expansion_info(db)?; | ||
32 | |||
33 | // the input node has only one token ? | ||
34 | let single = node.value.first_token()? == node.value.last_token()?; | ||
35 | |||
20 | // FIXME: We should handle recurside macro expansions | 36 | // FIXME: We should handle recurside macro expansions |
37 | let (range, origin) = node.value.descendants().find_map(|it| { | ||
38 | let first = it.first_token()?; | ||
39 | let last = it.last_token()?; | ||
21 | 40 | ||
22 | let range = node.value.descendants_with_tokens().find_map(|it| { | 41 | if !single && first == last { |
23 | match it.as_token() { | 42 | return None; |
24 | // FIXME: Remove this branch after all `tt::TokenTree`s have a proper `TokenId`, | ||
25 | // and return the range of the overall macro expansions if mapping first and last tokens fails. | ||
26 | Some(token) => { | ||
27 | let token = expansion.map_token_up(node.with_value(&token))?; | ||
28 | Some(token.with_value(token.value.text_range())) | ||
29 | } | ||
30 | None => { | ||
31 | // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens | ||
32 | let n = it.into_node()?; | ||
33 | let first = expansion.map_token_up(node.with_value(&n.first_token()?))?; | ||
34 | let last = expansion.map_token_up(node.with_value(&n.last_token()?))?; | ||
35 | |||
36 | // FIXME: Is is possible ? | ||
37 | if first.file_id != last.file_id { | ||
38 | return None; | ||
39 | } | ||
40 | |||
41 | // FIXME: Add union method in TextRange | ||
42 | let range = union_range(first.value.text_range(), last.value.text_range()); | ||
43 | Some(first.with_value(range)) | ||
44 | } | ||
45 | } | 43 | } |
46 | }); | ||
47 | 44 | ||
48 | return match range { | 45 | // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens |
49 | Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.value }, | 46 | let (first, first_origin) = expansion.map_token_up(node.with_value(&first))?; |
50 | None => { | 47 | let (last, last_origin) = expansion.map_token_up(node.with_value(&last))?; |
51 | FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } | 48 | |
49 | if first.file_id != last.file_id || first_origin != last_origin { | ||
50 | return None; | ||
52 | } | 51 | } |
53 | }; | 52 | |
53 | // FIXME: Add union method in TextRange | ||
54 | Some(( | ||
55 | first.with_value(union_range(first.value.text_range(), last.value.text_range())), | ||
56 | first_origin, | ||
57 | )) | ||
58 | })?; | ||
59 | |||
60 | return Some(( | ||
61 | FileRange { file_id: range.file_id.original_file(db), range: range.value }, | ||
62 | origin, | ||
63 | )); | ||
54 | 64 | ||
55 | fn union_range(a: TextRange, b: TextRange) -> TextRange { | 65 | fn union_range(a: TextRange, b: TextRange) -> TextRange { |
56 | let start = a.start().min(b.start()); | 66 | let start = a.start().min(b.start()); |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 27052d72b..bee8e9df2 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -221,7 +221,7 @@ fn named_target(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Option<Navigati | |||
221 | 221 | ||
222 | #[cfg(test)] | 222 | #[cfg(test)] |
223 | mod tests { | 223 | mod tests { |
224 | use test_utils::covers; | 224 | use test_utils::{assert_eq_text, covers}; |
225 | 225 | ||
226 | use crate::mock_analysis::analysis_and_position; | 226 | use crate::mock_analysis::analysis_and_position; |
227 | 227 | ||
@@ -234,6 +234,24 @@ mod tests { | |||
234 | nav.assert_match(expected); | 234 | nav.assert_match(expected); |
235 | } | 235 | } |
236 | 236 | ||
237 | fn check_goto_with_range_content(fixture: &str, expected: &str, expected_range: &str) { | ||
238 | let (analysis, pos) = analysis_and_position(fixture); | ||
239 | |||
240 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; | ||
241 | assert_eq!(navs.len(), 1); | ||
242 | let nav = navs.pop().unwrap(); | ||
243 | let file_text = analysis.file_text(pos.file_id).unwrap(); | ||
244 | |||
245 | let actual_full_range = &file_text[nav.full_range()]; | ||
246 | let actual_range = &file_text[nav.range()]; | ||
247 | |||
248 | test_utils::assert_eq_text!( | ||
249 | &format!("{}|{}", actual_full_range, actual_range), | ||
250 | expected_range | ||
251 | ); | ||
252 | nav.assert_match(expected); | ||
253 | } | ||
254 | |||
237 | #[test] | 255 | #[test] |
238 | fn goto_definition_works_in_items() { | 256 | fn goto_definition_works_in_items() { |
239 | check_goto( | 257 | check_goto( |
@@ -363,28 +381,27 @@ mod tests { | |||
363 | 381 | ||
364 | #[test] | 382 | #[test] |
365 | fn goto_definition_works_for_macro_defined_fn_with_arg() { | 383 | fn goto_definition_works_for_macro_defined_fn_with_arg() { |
366 | check_goto( | 384 | check_goto_with_range_content( |
367 | " | 385 | " |
368 | //- /lib.rs | 386 | //- /lib.rs |
369 | macro_rules! define_fn { | 387 | macro_rules! define_fn { |
370 | ($name:ident) => (fn $name() {}) | 388 | ($name:ident) => (fn $name() {}) |
371 | } | 389 | } |
372 | 390 | ||
373 | define_fn!( | 391 | define_fn!(foo); |
374 | foo | ||
375 | ) | ||
376 | 392 | ||
377 | fn bar() { | 393 | fn bar() { |
378 | <|>foo(); | 394 | <|>foo(); |
379 | } | 395 | } |
380 | ", | 396 | ", |
381 | "foo FN_DEF FileId(1) [80; 83) [80; 83)", | 397 | "foo FN_DEF FileId(1) [64; 80) [75; 78)", |
398 | "define_fn!(foo);|foo", | ||
382 | ); | 399 | ); |
383 | } | 400 | } |
384 | 401 | ||
385 | #[test] | 402 | #[test] |
386 | fn goto_definition_works_for_macro_defined_fn_no_arg() { | 403 | fn goto_definition_works_for_macro_defined_fn_no_arg() { |
387 | check_goto( | 404 | check_goto_with_range_content( |
388 | " | 405 | " |
389 | //- /lib.rs | 406 | //- /lib.rs |
390 | macro_rules! define_fn { | 407 | macro_rules! define_fn { |
@@ -397,7 +414,8 @@ mod tests { | |||
397 | <|>foo(); | 414 | <|>foo(); |
398 | } | 415 | } |
399 | ", | 416 | ", |
400 | "foo FN_DEF FileId(1) [39; 42) [39; 42)", | 417 | "foo FN_DEF FileId(1) [51; 64) [51; 64)", |
418 | "define_fn!();|define_fn!();", | ||
401 | ); | 419 | ); |
402 | } | 420 | } |
403 | 421 | ||
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 40605d9ef..2157139f6 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -7,9 +7,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .function { color: #93E0E3; } | 8 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 9 | .parameter { color: #94BFF3; } |
10 | .builtin { color: #DD6718; } | ||
11 | .text { color: #DCDCCC; } | 10 | .text { color: #DCDCCC; } |
12 | .type { color: #7CB8BB; } | 11 | .type { color: #7CB8BB; } |
12 | .type\.builtin { color: #8CD0D3; } | ||
13 | .type\.param { color: #20999D; } | 13 | .type\.param { color: #20999D; } |
14 | .attribute { color: #94BFF3; } | 14 | .attribute { color: #94BFF3; } |
15 | .literal { color: #BFEBBF; } | 15 | .literal { color: #BFEBBF; } |
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index ecf26c708..871a52cf6 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -7,9 +7,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .function { color: #93E0E3; } | 8 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 9 | .parameter { color: #94BFF3; } |
10 | .builtin { color: #DD6718; } | ||
11 | .text { color: #DCDCCC; } | 10 | .text { color: #DCDCCC; } |
12 | .type { color: #7CB8BB; } | 11 | .type { color: #7CB8BB; } |
12 | .type\.builtin { color: #8CD0D3; } | ||
13 | .type\.param { color: #20999D; } | 13 | .type\.param { color: #20999D; } |
14 | .attribute { color: #94BFF3; } | 14 | .attribute { color: #94BFF3; } |
15 | .literal { color: #BFEBBF; } | 15 | .literal { color: #BFEBBF; } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index eb3dd1779..15e75709c 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -284,9 +284,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
284 | .string { color: #CC9393; } | 284 | .string { color: #CC9393; } |
285 | .function { color: #93E0E3; } | 285 | .function { color: #93E0E3; } |
286 | .parameter { color: #94BFF3; } | 286 | .parameter { color: #94BFF3; } |
287 | .builtin { color: #DD6718; } | ||
288 | .text { color: #DCDCCC; } | 287 | .text { color: #DCDCCC; } |
289 | .type { color: #7CB8BB; } | 288 | .type { color: #7CB8BB; } |
289 | .type\\.builtin { color: #8CD0D3; } | ||
290 | .type\\.param { color: #20999D; } | 290 | .type\\.param { color: #20999D; } |
291 | .attribute { color: #94BFF3; } | 291 | .attribute { color: #94BFF3; } |
292 | .literal { color: #BFEBBF; } | 292 | .literal { color: #BFEBBF; } |
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 0d2d43bef..ce2deadf6 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -104,6 +104,7 @@ impl Shift { | |||
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | #[derive(Debug, Eq, PartialEq)] | ||
107 | pub enum Origin { | 108 | pub enum Origin { |
108 | Def, | 109 | Def, |
109 | Call, | 110 | Call, |
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index f06191963..09f0a2d98 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -248,7 +248,12 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { | |||
248 | p.error("expected `{`"); | 248 | p.error("expected `{`"); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | expr(p); | 251 | |
252 | if p.at_ts(EXPR_FIRST) { | ||
253 | expr(p); | ||
254 | } else { | ||
255 | p.error("expected expression"); | ||
256 | } | ||
252 | m.complete(p, LAMBDA_EXPR) | 257 | m.complete(p, LAMBDA_EXPR) |
253 | } | 258 | } |
254 | 259 | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs new file mode 100644 index 000000000..a2f74bd87 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | fn foo() -> i32 { | ||
2 | [1, 2, 3].iter() | ||
3 | .map(|it|) | ||
4 | .max::<i32>(); | ||
5 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt new file mode 100644 index 000000000..d1544634c --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt | |||
@@ -0,0 +1,83 @@ | |||
1 | SOURCE_FILE@[0; 83) | ||
2 | FN_DEF@[0; 82) | ||
3 | FN_KW@[0; 2) "fn" | ||
4 | WHITESPACE@[2; 3) " " | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) "(" | ||
9 | R_PAREN@[7; 8) ")" | ||
10 | WHITESPACE@[8; 9) " " | ||
11 | RET_TYPE@[9; 15) | ||
12 | THIN_ARROW@[9; 11) "->" | ||
13 | WHITESPACE@[11; 12) " " | ||
14 | PATH_TYPE@[12; 15) | ||
15 | PATH@[12; 15) | ||
16 | PATH_SEGMENT@[12; 15) | ||
17 | NAME_REF@[12; 15) | ||
18 | IDENT@[12; 15) "i32" | ||
19 | WHITESPACE@[15; 16) " " | ||
20 | BLOCK_EXPR@[16; 82) | ||
21 | BLOCK@[16; 82) | ||
22 | L_CURLY@[16; 17) "{" | ||
23 | WHITESPACE@[17; 22) "\n " | ||
24 | EXPR_STMT@[22; 80) | ||
25 | METHOD_CALL_EXPR@[22; 79) | ||
26 | METHOD_CALL_EXPR@[22; 57) | ||
27 | METHOD_CALL_EXPR@[22; 38) | ||
28 | ARRAY_EXPR@[22; 31) | ||
29 | L_BRACK@[22; 23) "[" | ||
30 | LITERAL@[23; 24) | ||
31 | INT_NUMBER@[23; 24) "1" | ||
32 | COMMA@[24; 25) "," | ||
33 | WHITESPACE@[25; 26) " " | ||
34 | LITERAL@[26; 27) | ||
35 | INT_NUMBER@[26; 27) "2" | ||
36 | COMMA@[27; 28) "," | ||
37 | WHITESPACE@[28; 29) " " | ||
38 | LITERAL@[29; 30) | ||
39 | INT_NUMBER@[29; 30) "3" | ||
40 | R_BRACK@[30; 31) "]" | ||
41 | DOT@[31; 32) "." | ||
42 | NAME_REF@[32; 36) | ||
43 | IDENT@[32; 36) "iter" | ||
44 | ARG_LIST@[36; 38) | ||
45 | L_PAREN@[36; 37) "(" | ||
46 | R_PAREN@[37; 38) ")" | ||
47 | WHITESPACE@[38; 47) "\n " | ||
48 | DOT@[47; 48) "." | ||
49 | NAME_REF@[48; 51) | ||
50 | IDENT@[48; 51) "map" | ||
51 | ARG_LIST@[51; 57) | ||
52 | L_PAREN@[51; 52) "(" | ||
53 | LAMBDA_EXPR@[52; 56) | ||
54 | PARAM_LIST@[52; 56) | ||
55 | PIPE@[52; 53) "|" | ||
56 | PARAM@[53; 55) | ||
57 | BIND_PAT@[53; 55) | ||
58 | NAME@[53; 55) | ||
59 | IDENT@[53; 55) "it" | ||
60 | PIPE@[55; 56) "|" | ||
61 | R_PAREN@[56; 57) ")" | ||
62 | WHITESPACE@[57; 66) "\n " | ||
63 | DOT@[66; 67) "." | ||
64 | NAME_REF@[67; 70) | ||
65 | IDENT@[67; 70) "max" | ||
66 | TYPE_ARG_LIST@[70; 77) | ||
67 | COLONCOLON@[70; 72) "::" | ||
68 | L_ANGLE@[72; 73) "<" | ||
69 | TYPE_ARG@[73; 76) | ||
70 | PATH_TYPE@[73; 76) | ||
71 | PATH@[73; 76) | ||
72 | PATH_SEGMENT@[73; 76) | ||
73 | NAME_REF@[73; 76) | ||
74 | IDENT@[73; 76) "i32" | ||
75 | R_ANGLE@[76; 77) ">" | ||
76 | ARG_LIST@[77; 79) | ||
77 | L_PAREN@[77; 78) "(" | ||
78 | R_PAREN@[78; 79) ")" | ||
79 | SEMI@[79; 80) ";" | ||
80 | WHITESPACE@[80; 81) "\n" | ||
81 | R_CURLY@[81; 82) "}" | ||
82 | WHITESPACE@[82; 83) "\n" | ||
83 | error 56: expected expression | ||
diff --git a/editors/code/package.json b/editors/code/package.json index ad1ba82ef..f2e8e647e 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -220,7 +220,7 @@ | |||
220 | }, | 220 | }, |
221 | "rust-analyzer.useClientWatching": { | 221 | "rust-analyzer.useClientWatching": { |
222 | "type": "boolean", | 222 | "type": "boolean", |
223 | "default": false, | 223 | "default": true, |
224 | "description": "client provided file watching instead of notify watching." | 224 | "description": "client provided file watching instead of notify watching." |
225 | }, | 225 | }, |
226 | "rust-analyzer.cargo-watch.arguments": { | 226 | "rust-analyzer.cargo-watch.arguments": { |
@@ -238,6 +238,11 @@ | |||
238 | "description": "A list of patterns for cargo-watch to ignore (will be passed as `--ignore`)", | 238 | "description": "A list of patterns for cargo-watch to ignore (will be passed as `--ignore`)", |
239 | "default": [] | 239 | "default": [] |
240 | }, | 240 | }, |
241 | "rust-analyzer.cargo-watch.allTargets": { | ||
242 | "type": "boolean", | ||
243 | "description": "Check all targets and tests (will be passed as `--all-targets`)", | ||
244 | "default": true | ||
245 | }, | ||
241 | "rust-analyzer.trace.server": { | 246 | "rust-analyzer.trace.server": { |
242 | "type": "string", | 247 | "type": "string", |
243 | "scope": "window", | 248 | "scope": "window", |
@@ -525,7 +530,7 @@ | |||
525 | }, | 530 | }, |
526 | { | 531 | { |
527 | "id": "ralsp.type.lifetime", | 532 | "id": "ralsp.type.lifetime", |
528 | "description": "Color for `Self` param type", | 533 | "description": "Color for lifetimes parameters", |
529 | "defaults": { | 534 | "defaults": { |
530 | "dark": "#4EC9B0", | 535 | "dark": "#4EC9B0", |
531 | "light": "#267F99", | 536 | "light": "#267F99", |
diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 512362eb1..748be535c 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts | |||
@@ -82,8 +82,10 @@ export class CargoWatchProvider implements vscode.Disposable { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | let args = | 84 | let args = |
85 | Server.config.cargoWatchOptions.command + | 85 | Server.config.cargoWatchOptions.command + ' --message-format json'; |
86 | ' --all-targets --message-format json'; | 86 | if (Server.config.cargoWatchOptions.allTargets) { |
87 | args += ' --all-targets'; | ||
88 | } | ||
87 | if (Server.config.cargoWatchOptions.command.length > 0) { | 89 | if (Server.config.cargoWatchOptions.command.length > 0) { |
88 | // Excape the double quote string: | 90 | // Excape the double quote string: |
89 | args += ' ' + Server.config.cargoWatchOptions.arguments; | 91 | args += ' ' + Server.config.cargoWatchOptions.arguments; |
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index defdfeb9c..e131f09df 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -13,6 +13,7 @@ export interface CargoWatchOptions { | |||
13 | command: string; | 13 | command: string; |
14 | trace: CargoWatchTraceOptions; | 14 | trace: CargoWatchTraceOptions; |
15 | ignore: string[]; | 15 | ignore: string[]; |
16 | allTargets: boolean; | ||
16 | } | 17 | } |
17 | 18 | ||
18 | export interface CargoFeatures { | 19 | export interface CargoFeatures { |
@@ -30,7 +31,7 @@ export class Config { | |||
30 | public displayInlayHints = true; | 31 | public displayInlayHints = true; |
31 | public maxInlayHintLength: null | number = null; | 32 | public maxInlayHintLength: null | number = null; |
32 | public excludeGlobs = []; | 33 | public excludeGlobs = []; |
33 | public useClientWatching = false; | 34 | public useClientWatching = true; |
34 | public featureFlags = {}; | 35 | public featureFlags = {}; |
35 | // for internal use | 36 | // for internal use |
36 | public withSysroot: null | boolean = null; | 37 | public withSysroot: null | boolean = null; |
@@ -40,6 +41,7 @@ export class Config { | |||
40 | arguments: '', | 41 | arguments: '', |
41 | command: '', | 42 | command: '', |
42 | ignore: [], | 43 | ignore: [], |
44 | allTargets: true, | ||
43 | }; | 45 | }; |
44 | public cargoFeatures: CargoFeatures = { | 46 | public cargoFeatures: CargoFeatures = { |
45 | noDefaultFeatures: false, | 47 | noDefaultFeatures: false, |
@@ -132,6 +134,13 @@ export class Config { | |||
132 | ); | 134 | ); |
133 | } | 135 | } |
134 | 136 | ||
137 | if (config.has('cargo-watch.allTargets')) { | ||
138 | this.cargoWatchOptions.allTargets = config.get<boolean>( | ||
139 | 'cargo-watch.allTargets', | ||
140 | true, | ||
141 | ); | ||
142 | } | ||
143 | |||
135 | if (config.has('lruCapacity')) { | 144 | if (config.has('lruCapacity')) { |
136 | this.lruCapacity = config.get('lruCapacity') as number; | 145 | this.lruCapacity = config.get('lruCapacity') as number; |
137 | } | 146 | } |
@@ -148,7 +157,7 @@ export class Config { | |||
148 | this.excludeGlobs = config.get('excludeGlobs') || []; | 157 | this.excludeGlobs = config.get('excludeGlobs') || []; |
149 | } | 158 | } |
150 | if (config.has('useClientWatching')) { | 159 | if (config.has('useClientWatching')) { |
151 | this.useClientWatching = config.get('useClientWatching') || false; | 160 | this.useClientWatching = config.get('useClientWatching') || true; |
152 | } | 161 | } |
153 | if (config.has('featureFlags')) { | 162 | if (config.has('featureFlags')) { |
154 | this.featureFlags = config.get('featureFlags') || {}; | 163 | this.featureFlags = config.get('featureFlags') || {}; |
diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index d7c0ae131..e1b0d13e7 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts | |||
@@ -52,12 +52,12 @@ export class Highlighter { | |||
52 | decoration('function'), | 52 | decoration('function'), |
53 | decoration('parameter'), | 53 | decoration('parameter'), |
54 | decoration('constant'), | 54 | decoration('constant'), |
55 | decoration('type'), | 55 | decoration('type.builtin'), |
56 | decoration('type.self'), | ||
57 | decoration('type.generic'), | 56 | decoration('type.generic'), |
58 | decoration('type.param'), | ||
59 | decoration('type.lifetime'), | 57 | decoration('type.lifetime'), |
60 | decoration('builtin'), | 58 | decoration('type.param'), |
59 | decoration('type.self'), | ||
60 | decoration('type'), | ||
61 | decoration('text'), | 61 | decoration('text'), |
62 | decoration('attribute'), | 62 | decoration('attribute'), |
63 | decoration('literal'), | 63 | decoration('literal'), |