diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | 206 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 85 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 2 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 9 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 129 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 143 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 53 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 65 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/subscriptions.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/req.rs | 36 | ||||
-rw-r--r-- | crates/rust-analyzer/src/vfs_glob.rs | 10 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 57 |
19 files changed, 553 insertions, 300 deletions
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs new file mode 100644 index 000000000..864373aa5 --- /dev/null +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | |||
@@ -0,0 +1,206 @@ | |||
1 | use ra_syntax::{ | ||
2 | ast::{self, AstNode, NameOwner}, | ||
3 | TextUnit, | ||
4 | }; | ||
5 | use stdx::format_to; | ||
6 | |||
7 | use crate::{Assist, AssistCtx, AssistId}; | ||
8 | use ra_ide_db::RootDatabase; | ||
9 | |||
10 | // Assist add_from_impl_for_enum | ||
11 | // | ||
12 | // Adds a From impl for an enum variant with one tuple field | ||
13 | // | ||
14 | // ``` | ||
15 | // enum A { <|>One(u32) } | ||
16 | // ``` | ||
17 | // -> | ||
18 | // ``` | ||
19 | // enum A { One(u32) } | ||
20 | // | ||
21 | // impl From<u32> for A { | ||
22 | // fn from(v: u32) -> Self { | ||
23 | // A::One(v) | ||
24 | // } | ||
25 | // } | ||
26 | // ``` | ||
27 | pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> { | ||
28 | let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?; | ||
29 | let variant_name = variant.name()?; | ||
30 | let enum_name = variant.parent_enum().name()?; | ||
31 | let field_list = match variant.kind() { | ||
32 | ast::StructKind::Tuple(field_list) => field_list, | ||
33 | _ => return None, | ||
34 | }; | ||
35 | if field_list.fields().count() != 1 { | ||
36 | return None; | ||
37 | } | ||
38 | let field_type = field_list.fields().next()?.type_ref()?; | ||
39 | let path = match field_type { | ||
40 | ast::TypeRef::PathType(p) => p, | ||
41 | _ => return None, | ||
42 | }; | ||
43 | |||
44 | if already_has_from_impl(ctx.sema, &variant) { | ||
45 | return None; | ||
46 | } | ||
47 | |||
48 | ctx.add_assist( | ||
49 | AssistId("add_from_impl_for_enum"), | ||
50 | "Add From impl for this enum variant", | ||
51 | |edit| { | ||
52 | let start_offset = variant.parent_enum().syntax().text_range().end(); | ||
53 | let mut buf = String::new(); | ||
54 | format_to!( | ||
55 | buf, | ||
56 | r#" | ||
57 | |||
58 | impl From<{0}> for {1} {{ | ||
59 | fn from(v: {0}) -> Self {{ | ||
60 | {1}::{2}(v) | ||
61 | }} | ||
62 | }}"#, | ||
63 | path.syntax(), | ||
64 | enum_name, | ||
65 | variant_name | ||
66 | ); | ||
67 | edit.insert(start_offset, buf); | ||
68 | edit.set_cursor(start_offset + TextUnit::of_str("\n\n")); | ||
69 | }, | ||
70 | ) | ||
71 | } | ||
72 | |||
73 | fn already_has_from_impl( | ||
74 | sema: &'_ hir::Semantics<'_, RootDatabase>, | ||
75 | variant: &ast::EnumVariant, | ||
76 | ) -> bool { | ||
77 | let scope = sema.scope(&variant.syntax()); | ||
78 | |||
79 | let from_path = ast::make::path_from_text("From"); | ||
80 | let from_hir_path = match hir::Path::from_ast(from_path) { | ||
81 | Some(p) => p, | ||
82 | None => return false, | ||
83 | }; | ||
84 | let from_trait = match scope.resolve_hir_path(&from_hir_path) { | ||
85 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(t))) => t, | ||
86 | _ => return false, | ||
87 | }; | ||
88 | |||
89 | let e: hir::Enum = match sema.to_def(&variant.parent_enum()) { | ||
90 | Some(e) => e, | ||
91 | None => return false, | ||
92 | }; | ||
93 | let e_ty = e.ty(sema.db); | ||
94 | |||
95 | let hir_enum_var: hir::EnumVariant = match sema.to_def(variant) { | ||
96 | Some(ev) => ev, | ||
97 | None => return false, | ||
98 | }; | ||
99 | let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db); | ||
100 | |||
101 | e_ty.impls_trait(sema.db, from_trait, &[var_ty.clone()]) | ||
102 | } | ||
103 | |||
104 | #[cfg(test)] | ||
105 | mod tests { | ||
106 | use super::*; | ||
107 | use crate::helpers::{check_assist, check_assist_not_applicable}; | ||
108 | |||
109 | #[test] | ||
110 | fn test_add_from_impl_for_enum() { | ||
111 | check_assist( | ||
112 | add_from_impl_for_enum, | ||
113 | "enum A { <|>One(u32) }", | ||
114 | r#"enum A { One(u32) } | ||
115 | |||
116 | <|>impl From<u32> for A { | ||
117 | fn from(v: u32) -> Self { | ||
118 | A::One(v) | ||
119 | } | ||
120 | }"#, | ||
121 | ); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn test_add_from_impl_for_enum_complicated_path() { | ||
126 | check_assist( | ||
127 | add_from_impl_for_enum, | ||
128 | "enum A { <|>One(foo::bar::baz::Boo) }", | ||
129 | r#"enum A { One(foo::bar::baz::Boo) } | ||
130 | |||
131 | <|>impl From<foo::bar::baz::Boo> for A { | ||
132 | fn from(v: foo::bar::baz::Boo) -> Self { | ||
133 | A::One(v) | ||
134 | } | ||
135 | }"#, | ||
136 | ); | ||
137 | } | ||
138 | |||
139 | #[test] | ||
140 | fn test_add_from_impl_no_element() { | ||
141 | check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One }"); | ||
142 | } | ||
143 | |||
144 | #[test] | ||
145 | fn test_add_from_impl_more_than_one_element_in_tuple() { | ||
146 | check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One(u32, String) }"); | ||
147 | } | ||
148 | |||
149 | #[test] | ||
150 | fn test_add_from_impl_struct_variant() { | ||
151 | check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One { x: u32 } }"); | ||
152 | } | ||
153 | |||
154 | #[test] | ||
155 | fn test_add_from_impl_already_exists() { | ||
156 | check_assist_not_applicable( | ||
157 | add_from_impl_for_enum, | ||
158 | r#"enum A { <|>One(u32), } | ||
159 | |||
160 | impl From<u32> for A { | ||
161 | fn from(v: u32) -> Self { | ||
162 | A::One(v) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | pub trait From<T> { | ||
167 | fn from(T) -> Self; | ||
168 | }"#, | ||
169 | ); | ||
170 | } | ||
171 | |||
172 | #[test] | ||
173 | fn test_add_from_impl_different_variant_impl_exists() { | ||
174 | check_assist( | ||
175 | add_from_impl_for_enum, | ||
176 | r#"enum A { <|>One(u32), Two(String), } | ||
177 | |||
178 | impl From<String> for A { | ||
179 | fn from(v: String) -> Self { | ||
180 | A::Two(v) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | pub trait From<T> { | ||
185 | fn from(T) -> Self; | ||
186 | }"#, | ||
187 | r#"enum A { One(u32), Two(String), } | ||
188 | |||
189 | <|>impl From<u32> for A { | ||
190 | fn from(v: u32) -> Self { | ||
191 | A::One(v) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | impl From<String> for A { | ||
196 | fn from(v: String) -> Self { | ||
197 | A::Two(v) | ||
198 | } | ||
199 | } | ||
200 | |||
201 | pub trait From<T> { | ||
202 | fn from(T) -> Self; | ||
203 | }"#, | ||
204 | ); | ||
205 | } | ||
206 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 66854cb5a..fa3d3913f 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -123,6 +123,7 @@ mod handlers { | |||
123 | mod replace_qualified_name_with_use; | 123 | mod replace_qualified_name_with_use; |
124 | mod replace_unwrap_with_match; | 124 | mod replace_unwrap_with_match; |
125 | mod split_import; | 125 | mod split_import; |
126 | mod add_from_impl_for_enum; | ||
126 | 127 | ||
127 | pub(crate) fn all() -> &'static [AssistHandler] { | 128 | pub(crate) fn all() -> &'static [AssistHandler] { |
128 | &[ | 129 | &[ |
@@ -161,6 +162,7 @@ mod handlers { | |||
161 | replace_qualified_name_with_use::replace_qualified_name_with_use, | 162 | replace_qualified_name_with_use::replace_qualified_name_with_use, |
162 | replace_unwrap_with_match::replace_unwrap_with_match, | 163 | replace_unwrap_with_match::replace_unwrap_with_match, |
163 | split_import::split_import, | 164 | split_import::split_import, |
165 | add_from_impl_for_enum::add_from_impl_for_enum, | ||
164 | ] | 166 | ] |
165 | } | 167 | } |
166 | } | 168 | } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index cd2a8fc62..c6f3bdb8e 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1084,6 +1084,26 @@ impl Type { | |||
1084 | ) | 1084 | ) |
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { | ||
1088 | let trait_ref = hir_ty::TraitRef { | ||
1089 | trait_: trait_.id, | ||
1090 | substs: Substs::build_for_def(db, trait_.id) | ||
1091 | .push(self.ty.value.clone()) | ||
1092 | .fill(args.iter().map(|t| t.ty.value.clone())) | ||
1093 | .build(), | ||
1094 | }; | ||
1095 | |||
1096 | let goal = Canonical { | ||
1097 | value: hir_ty::InEnvironment::new( | ||
1098 | self.ty.environment.clone(), | ||
1099 | hir_ty::Obligation::Trait(trait_ref), | ||
1100 | ), | ||
1101 | num_vars: 0, | ||
1102 | }; | ||
1103 | |||
1104 | db.trait_solve(self.krate, goal).is_some() | ||
1105 | } | ||
1106 | |||
1087 | // FIXME: this method is broken, as it doesn't take closures into account. | 1107 | // FIXME: this method is broken, as it doesn't take closures into account. |
1088 | pub fn as_callable(&self) -> Option<CallableDef> { | 1108 | pub fn as_callable(&self) -> Option<CallableDef> { |
1089 | Some(self.ty.value.as_callable()?.0) | 1109 | Some(self.ty.value.as_callable()?.0) |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index baed6225b..86acd27f8 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -11,7 +11,7 @@ use hir_def::{ | |||
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use super::{BindingMode, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 15 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; |
16 | 16 | ||
17 | impl<'a> InferenceContext<'a> { | 17 | impl<'a> InferenceContext<'a> { |
@@ -198,7 +198,14 @@ impl<'a> InferenceContext<'a> { | |||
198 | 198 | ||
199 | Ty::apply_one(container_ty, elem_ty) | 199 | Ty::apply_one(container_ty, elem_ty) |
200 | } | 200 | } |
201 | _ => Ty::Unknown, | 201 | Pat::Wild => expected.clone(), |
202 | Pat::Range { start, end } => { | ||
203 | let start_ty = self.infer_expr(*start, &Expectation::has_type(expected.clone())); | ||
204 | let end_ty = self.infer_expr(*end, &Expectation::has_type(start_ty)); | ||
205 | end_ty | ||
206 | } | ||
207 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | ||
208 | Pat::Missing => Ty::Unknown, | ||
202 | }; | 209 | }; |
203 | // use a new type variable if we got Ty::Unknown here | 210 | // use a new type variable if we got Ty::Unknown here |
204 | let ty = self.insert_type_vars_shallow(ty); | 211 | let ty = self.insert_type_vars_shallow(ty); |
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 1e303f5ce..3e3d55c04 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -275,12 +275,14 @@ fn test(i: i32) { | |||
275 | [70; 147) 'match ... }': &[i32] | 275 | [70; 147) 'match ... }': &[i32] |
276 | [76; 77) 'i': i32 | 276 | [76; 77) 'i': i32 |
277 | [88; 89) '2': i32 | 277 | [88; 89) '2': i32 |
278 | [88; 89) '2': i32 | ||
278 | [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32] | 279 | [93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
279 | [93; 102) 'foo(&[2])': &[i32] | 280 | [93; 102) 'foo(&[2])': &[i32] |
280 | [97; 101) '&[2]': &[i32; _] | 281 | [97; 101) '&[2]': &[i32; _] |
281 | [98; 101) '[2]': [i32; _] | 282 | [98; 101) '[2]': [i32; _] |
282 | [99; 100) '2': i32 | 283 | [99; 100) '2': i32 |
283 | [112; 113) '1': i32 | 284 | [112; 113) '1': i32 |
285 | [112; 113) '1': i32 | ||
284 | [117; 121) '&[1]': &[i32; _] | 286 | [117; 121) '&[1]': &[i32; _] |
285 | [118; 121) '[1]': [i32; _] | 287 | [118; 121) '[1]': [i32; _] |
286 | [119; 120) '1': i32 | 288 | [119; 120) '1': i32 |
@@ -316,10 +318,12 @@ fn test(i: i32) { | |||
316 | [70; 147) 'match ... }': &[i32] | 318 | [70; 147) 'match ... }': &[i32] |
317 | [76; 77) 'i': i32 | 319 | [76; 77) 'i': i32 |
318 | [88; 89) '1': i32 | 320 | [88; 89) '1': i32 |
321 | [88; 89) '1': i32 | ||
319 | [93; 97) '&[1]': &[i32; _] | 322 | [93; 97) '&[1]': &[i32; _] |
320 | [94; 97) '[1]': [i32; _] | 323 | [94; 97) '[1]': [i32; _] |
321 | [95; 96) '1': i32 | 324 | [95; 96) '1': i32 |
322 | [107; 108) '2': i32 | 325 | [107; 108) '2': i32 |
326 | [107; 108) '2': i32 | ||
323 | [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32] | 327 | [112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32] |
324 | [112; 121) 'foo(&[2])': &[i32] | 328 | [112; 121) 'foo(&[2])': &[i32] |
325 | [116; 120) '&[2]': &[i32; _] | 329 | [116; 120) '&[2]': &[i32; _] |
@@ -357,9 +361,11 @@ fn test() { | |||
357 | [45; 142) 'match ... }': *const i32 | 361 | [45; 142) 'match ... }': *const i32 |
358 | [51; 52) '1': i32 | 362 | [51; 52) '1': i32 |
359 | [63; 64) '1': i32 | 363 | [63; 64) '1': i32 |
364 | [63; 64) '1': i32 | ||
360 | [68; 69) 't': &mut i32 | 365 | [68; 69) 't': &mut i32 |
361 | [68; 81) 't as *mut i32': *mut i32 | 366 | [68; 81) 't as *mut i32': *mut i32 |
362 | [91; 92) '2': i32 | 367 | [91; 92) '2': i32 |
368 | [91; 92) '2': i32 | ||
363 | [96; 97) 't': &mut i32 | 369 | [96; 97) 't': &mut i32 |
364 | [96; 105) 't as &i32': &i32 | 370 | [96; 105) 't as &i32': &i32 |
365 | [115; 116) '_': i32 | 371 | [115; 116) '_': i32 |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 76aa32024..6e5d2247c 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -82,6 +82,90 @@ fn test(x: &i32) { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | #[test] | 84 | #[test] |
85 | fn infer_literal_pattern() { | ||
86 | assert_snapshot!( | ||
87 | infer_with_mismatches(r#" | ||
88 | fn any<T>() -> T { loop {} } | ||
89 | fn test(x: &i32) { | ||
90 | if let "foo" = any() {} | ||
91 | if let 1 = any() {} | ||
92 | if let 1u32 = any() {} | ||
93 | if let 1f32 = any() {} | ||
94 | if let 1.0 = any() {} | ||
95 | if let true = any() {} | ||
96 | } | ||
97 | "#, true), | ||
98 | @r###" | ||
99 | [18; 29) '{ loop {} }': T | ||
100 | [20; 27) 'loop {}': ! | ||
101 | [25; 27) '{}': () | ||
102 | [38; 39) 'x': &i32 | ||
103 | [47; 209) '{ ...) {} }': () | ||
104 | [53; 76) 'if let...y() {}': () | ||
105 | [60; 65) '"foo"': &str | ||
106 | [60; 65) '"foo"': &str | ||
107 | [68; 71) 'any': fn any<&str>() -> &str | ||
108 | [68; 73) 'any()': &str | ||
109 | [74; 76) '{}': () | ||
110 | [81; 100) 'if let...y() {}': () | ||
111 | [88; 89) '1': i32 | ||
112 | [88; 89) '1': i32 | ||
113 | [92; 95) 'any': fn any<i32>() -> i32 | ||
114 | [92; 97) 'any()': i32 | ||
115 | [98; 100) '{}': () | ||
116 | [105; 127) 'if let...y() {}': () | ||
117 | [112; 116) '1u32': u32 | ||
118 | [112; 116) '1u32': u32 | ||
119 | [119; 122) 'any': fn any<u32>() -> u32 | ||
120 | [119; 124) 'any()': u32 | ||
121 | [125; 127) '{}': () | ||
122 | [132; 154) 'if let...y() {}': () | ||
123 | [139; 143) '1f32': f32 | ||
124 | [139; 143) '1f32': f32 | ||
125 | [146; 149) 'any': fn any<f32>() -> f32 | ||
126 | [146; 151) 'any()': f32 | ||
127 | [152; 154) '{}': () | ||
128 | [159; 180) 'if let...y() {}': () | ||
129 | [166; 169) '1.0': f64 | ||
130 | [166; 169) '1.0': f64 | ||
131 | [172; 175) 'any': fn any<f64>() -> f64 | ||
132 | [172; 177) 'any()': f64 | ||
133 | [178; 180) '{}': () | ||
134 | [185; 207) 'if let...y() {}': () | ||
135 | [192; 196) 'true': bool | ||
136 | [192; 196) 'true': bool | ||
137 | [199; 202) 'any': fn any<bool>() -> bool | ||
138 | [199; 204) 'any()': bool | ||
139 | [205; 207) '{}': () | ||
140 | "### | ||
141 | ); | ||
142 | } | ||
143 | |||
144 | #[test] | ||
145 | fn infer_range_pattern() { | ||
146 | assert_snapshot!( | ||
147 | infer_with_mismatches(r#" | ||
148 | fn test(x: &i32) { | ||
149 | if let 1..76 = 2u32 {} | ||
150 | if let 1..=76 = 2u32 {} | ||
151 | } | ||
152 | "#, true), | ||
153 | @r###" | ||
154 | [9; 10) 'x': &i32 | ||
155 | [18; 76) '{ ...2 {} }': () | ||
156 | [24; 46) 'if let...u32 {}': () | ||
157 | [31; 36) '1..76': u32 | ||
158 | [39; 43) '2u32': u32 | ||
159 | [44; 46) '{}': () | ||
160 | [51; 74) 'if let...u32 {}': () | ||
161 | [58; 64) '1..=76': u32 | ||
162 | [67; 71) '2u32': u32 | ||
163 | [72; 74) '{}': () | ||
164 | "### | ||
165 | ); | ||
166 | } | ||
167 | |||
168 | #[test] | ||
85 | fn infer_pattern_match_ergonomics() { | 169 | fn infer_pattern_match_ergonomics() { |
86 | assert_snapshot!( | 170 | assert_snapshot!( |
87 | infer(r#" | 171 | infer(r#" |
@@ -212,6 +296,7 @@ fn test() { | |||
212 | [59; 62) 'arr': [f64; _] | 296 | [59; 62) 'arr': [f64; _] |
213 | [73; 81) '[1.0, a]': [f64; _] | 297 | [73; 81) '[1.0, a]': [f64; _] |
214 | [74; 77) '1.0': f64 | 298 | [74; 77) '1.0': f64 |
299 | [74; 77) '1.0': f64 | ||
215 | [79; 80) 'a': f64 | 300 | [79; 80) 'a': f64 |
216 | [85; 111) '{ ... }': () | 301 | [85; 111) '{ ... }': () |
217 | [99; 100) 'a': f64 | 302 | [99; 100) 'a': f64 |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index a02e3ee05..2ee9b8f10 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -206,7 +206,8 @@ pub fn compute() { | |||
206 | [24; 106) 'match ... }': () | 206 | [24; 106) 'match ... }': () |
207 | [30; 37) 'nope!()': {unknown} | 207 | [30; 37) 'nope!()': {unknown} |
208 | [48; 94) 'SizeSk...tail }': {unknown} | 208 | [48; 94) 'SizeSk...tail }': {unknown} |
209 | [82; 86) 'true': {unknown} | 209 | [82; 86) 'true': bool |
210 | [82; 86) 'true': bool | ||
210 | [88; 92) 'tail': {unknown} | 211 | [88; 92) 'tail': {unknown} |
211 | [98; 100) '{}': () | 212 | [98; 100) '{}': () |
212 | "### | 213 | "### |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index c140bd513..a600b947d 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -948,6 +948,7 @@ fn foo() { | |||
948 | [165; 247) 'match ... }': i32 | 948 | [165; 247) 'match ... }': i32 |
949 | [171; 175) 'true': bool | 949 | [171; 175) 'true': bool |
950 | [186; 190) 'true': bool | 950 | [186; 190) 'true': bool |
951 | [186; 190) 'true': bool | ||
951 | [194; 195) '3': i32 | 952 | [194; 195) '3': i32 |
952 | [205; 206) '_': bool | 953 | [205; 206) '_': bool |
953 | [210; 241) '{ ... }': ! | 954 | [210; 241) '{ ... }': ! |
@@ -956,6 +957,7 @@ fn foo() { | |||
956 | [263; 320) 'match ... }': i32 | 957 | [263; 320) 'match ... }': i32 |
957 | [269; 273) 'true': bool | 958 | [269; 273) 'true': bool |
958 | [284; 288) 'true': bool | 959 | [284; 288) 'true': bool |
960 | [284; 288) 'true': bool | ||
959 | [292; 293) '4': i32 | 961 | [292; 293) '4': i32 |
960 | [303; 304) '_': bool | 962 | [303; 304) '_': bool |
961 | [308; 314) 'return': ! | 963 | [308; 314) 'return': ! |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index c1b6e1ddc..b50cda06f 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -75,7 +75,7 @@ pub type Target = Idx<TargetData>; | |||
75 | 75 | ||
76 | #[derive(Debug, Clone)] | 76 | #[derive(Debug, Clone)] |
77 | pub struct PackageData { | 77 | pub struct PackageData { |
78 | pub id: String, | 78 | pub version: String, |
79 | pub name: String, | 79 | pub name: String, |
80 | pub manifest: PathBuf, | 80 | pub manifest: PathBuf, |
81 | pub targets: Vec<Target>, | 81 | pub targets: Vec<Target>, |
@@ -174,14 +174,15 @@ impl CargoWorkspace { | |||
174 | let ws_members = &meta.workspace_members; | 174 | let ws_members = &meta.workspace_members; |
175 | 175 | ||
176 | for meta_pkg in meta.packages { | 176 | for meta_pkg in meta.packages { |
177 | let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg; | 177 | let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } = |
178 | meta_pkg; | ||
178 | let is_member = ws_members.contains(&id); | 179 | let is_member = ws_members.contains(&id); |
179 | let edition = edition | 180 | let edition = edition |
180 | .parse::<Edition>() | 181 | .parse::<Edition>() |
181 | .with_context(|| format!("Failed to parse edition {}", edition))?; | 182 | .with_context(|| format!("Failed to parse edition {}", edition))?; |
182 | let pkg = packages.alloc(PackageData { | 183 | let pkg = packages.alloc(PackageData { |
183 | name, | 184 | name, |
184 | id: id.to_string(), | 185 | version: version.to_string(), |
185 | manifest: manifest_path, | 186 | manifest: manifest_path, |
186 | targets: Vec::new(), | 187 | targets: Vec::new(), |
187 | is_member, | 188 | is_member, |
@@ -256,7 +257,7 @@ impl CargoWorkspace { | |||
256 | if self.is_unique(&*package.name) { | 257 | if self.is_unique(&*package.name) { |
257 | package.name.clone() | 258 | package.name.clone() |
258 | } else { | 259 | } else { |
259 | package.id.clone() | 260 | format!("{}:{}", package.name, package.version) |
260 | } | 261 | } |
261 | } | 262 | } |
262 | 263 | ||
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index dd9c80691..0ab64a1e0 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -62,16 +62,16 @@ pub struct PackageRoot { | |||
62 | /// Is a member of the current workspace | 62 | /// Is a member of the current workspace |
63 | is_member: bool, | 63 | is_member: bool, |
64 | } | 64 | } |
65 | |||
66 | impl PackageRoot { | 65 | impl PackageRoot { |
67 | pub fn new(path: PathBuf, is_member: bool) -> PackageRoot { | 66 | pub fn new_member(path: PathBuf) -> PackageRoot { |
68 | PackageRoot { path, is_member } | 67 | Self { path, is_member: true } |
69 | } | 68 | } |
70 | 69 | pub fn new_non_member(path: PathBuf) -> PackageRoot { | |
71 | pub fn path(&self) -> &PathBuf { | 70 | Self { path, is_member: false } |
71 | } | ||
72 | pub fn path(&self) -> &Path { | ||
72 | &self.path | 73 | &self.path |
73 | } | 74 | } |
74 | |||
75 | pub fn is_member(&self) -> bool { | 75 | pub fn is_member(&self) -> bool { |
76 | self.is_member | 76 | self.is_member |
77 | } | 77 | } |
@@ -130,70 +130,45 @@ impl ProjectWorkspace { | |||
130 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 130 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
131 | match self { | 131 | match self { |
132 | ProjectWorkspace::Json { project } => { | 132 | ProjectWorkspace::Json { project } => { |
133 | let mut roots = Vec::with_capacity(project.roots.len()); | 133 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() |
134 | for root in &project.roots { | ||
135 | roots.push(PackageRoot::new(root.path.clone(), true)); | ||
136 | } | ||
137 | roots | ||
138 | } | ||
139 | ProjectWorkspace::Cargo { cargo, sysroot } => { | ||
140 | let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len()); | ||
141 | for pkg in cargo.packages() { | ||
142 | let root = cargo[pkg].root().to_path_buf(); | ||
143 | let member = cargo[pkg].is_member; | ||
144 | roots.push(PackageRoot::new(root, member)); | ||
145 | } | ||
146 | for krate in sysroot.crates() { | ||
147 | roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false)) | ||
148 | } | ||
149 | roots | ||
150 | } | 134 | } |
135 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | ||
136 | .packages() | ||
137 | .map(|pkg| PackageRoot { | ||
138 | path: cargo[pkg].root().to_path_buf(), | ||
139 | is_member: cargo[pkg].is_member, | ||
140 | }) | ||
141 | .chain(sysroot.crates().map(|krate| { | ||
142 | PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) | ||
143 | })) | ||
144 | .collect(), | ||
151 | } | 145 | } |
152 | } | 146 | } |
153 | 147 | ||
154 | pub fn out_dirs(&self) -> Vec<PathBuf> { | 148 | pub fn out_dirs(&self) -> Vec<PathBuf> { |
155 | match self { | 149 | match self { |
156 | ProjectWorkspace::Json { project } => { | 150 | ProjectWorkspace::Json { project } => { |
157 | let mut out_dirs = Vec::with_capacity(project.crates.len()); | 151 | project.crates.iter().filter_map(|krate| krate.out_dir.as_ref()).cloned().collect() |
158 | for krate in &project.crates { | ||
159 | if let Some(out_dir) = &krate.out_dir { | ||
160 | out_dirs.push(out_dir.to_path_buf()); | ||
161 | } | ||
162 | } | ||
163 | out_dirs | ||
164 | } | 152 | } |
165 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 153 | ProjectWorkspace::Cargo { cargo, sysroot: _ } => { |
166 | let mut out_dirs = Vec::with_capacity(cargo.packages().len()); | 154 | cargo.packages().filter_map(|pkg| cargo[pkg].out_dir.as_ref()).cloned().collect() |
167 | for pkg in cargo.packages() { | ||
168 | if let Some(out_dir) = &cargo[pkg].out_dir { | ||
169 | out_dirs.push(out_dir.to_path_buf()); | ||
170 | } | ||
171 | } | ||
172 | out_dirs | ||
173 | } | 155 | } |
174 | } | 156 | } |
175 | } | 157 | } |
176 | 158 | ||
177 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { | 159 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { |
178 | match self { | 160 | match self { |
179 | ProjectWorkspace::Json { project } => { | 161 | ProjectWorkspace::Json { project } => project |
180 | let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len()); | 162 | .crates |
181 | for krate in &project.crates { | 163 | .iter() |
182 | if let Some(out_dir) = &krate.proc_macro_dylib_path { | 164 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) |
183 | proc_macro_dylib_paths.push(out_dir.to_path_buf()); | 165 | .cloned() |
184 | } | 166 | .collect(), |
185 | } | 167 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo |
186 | proc_macro_dylib_paths | 168 | .packages() |
187 | } | 169 | .filter_map(|pkg| cargo[pkg].proc_macro_dylib_path.as_ref()) |
188 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 170 | .cloned() |
189 | let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len()); | 171 | .collect(), |
190 | for pkg in cargo.packages() { | ||
191 | if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path { | ||
192 | proc_macro_dylib_paths.push(dylib_path.to_path_buf()); | ||
193 | } | ||
194 | } | ||
195 | proc_macro_dylib_paths | ||
196 | } | ||
197 | } | 172 | } |
198 | } | 173 | } |
199 | 174 | ||
@@ -216,10 +191,12 @@ impl ProjectWorkspace { | |||
216 | let mut crate_graph = CrateGraph::default(); | 191 | let mut crate_graph = CrateGraph::default(); |
217 | match self { | 192 | match self { |
218 | ProjectWorkspace::Json { project } => { | 193 | ProjectWorkspace::Json { project } => { |
219 | let mut crates = FxHashMap::default(); | 194 | let crates: FxHashMap<_, _> = project |
220 | for (id, krate) in project.crates.iter().enumerate() { | 195 | .crates |
221 | let crate_id = json_project::CrateId(id); | 196 | .iter() |
222 | if let Some(file_id) = load(&krate.root_module) { | 197 | .enumerate() |
198 | .filter_map(|(seq_index, krate)| { | ||
199 | let file_id = load(&krate.root_module)?; | ||
223 | let edition = match krate.edition { | 200 | let edition = match krate.edition { |
224 | json_project::Edition::Edition2015 => Edition::Edition2015, | 201 | json_project::Edition::Edition2015 => Edition::Edition2015, |
225 | json_project::Edition::Edition2018 => Edition::Edition2018, | 202 | json_project::Edition::Edition2018 => Edition::Edition2018, |
@@ -249,8 +226,8 @@ impl ProjectWorkspace { | |||
249 | .clone() | 226 | .clone() |
250 | .map(|it| proc_macro_client.by_dylib_path(&it)); | 227 | .map(|it| proc_macro_client.by_dylib_path(&it)); |
251 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 228 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
252 | crates.insert( | 229 | Some(( |
253 | crate_id, | 230 | json_project::CrateId(seq_index), |
254 | crate_graph.add_crate_root( | 231 | crate_graph.add_crate_root( |
255 | file_id, | 232 | file_id, |
256 | edition, | 233 | edition, |
@@ -261,9 +238,9 @@ impl ProjectWorkspace { | |||
261 | extern_source, | 238 | extern_source, |
262 | proc_macro.unwrap_or_default(), | 239 | proc_macro.unwrap_or_default(), |
263 | ), | 240 | ), |
264 | ); | 241 | )) |
265 | } | 242 | }) |
266 | } | 243 | .collect(); |
267 | 244 | ||
268 | for (id, krate) in project.crates.iter().enumerate() { | 245 | for (id, krate) in project.crates.iter().enumerate() { |
269 | for dep in &krate.deps { | 246 | for dep in &krate.deps { |
@@ -287,9 +264,11 @@ impl ProjectWorkspace { | |||
287 | } | 264 | } |
288 | } | 265 | } |
289 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 266 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
290 | let mut sysroot_crates = FxHashMap::default(); | 267 | let sysroot_crates: FxHashMap<_, _> = sysroot |
291 | for krate in sysroot.crates() { | 268 | .crates() |
292 | if let Some(file_id) = load(&sysroot[krate].root) { | 269 | .filter_map(|krate| { |
270 | let file_id = load(&sysroot[krate].root)?; | ||
271 | |||
293 | // Crates from sysroot have `cfg(test)` disabled | 272 | // Crates from sysroot have `cfg(test)` disabled |
294 | let cfg_options = { | 273 | let cfg_options = { |
295 | let mut opts = default_cfg_options.clone(); | 274 | let mut opts = default_cfg_options.clone(); |
@@ -300,22 +279,22 @@ impl ProjectWorkspace { | |||
300 | let env = Env::default(); | 279 | let env = Env::default(); |
301 | let extern_source = ExternSource::default(); | 280 | let extern_source = ExternSource::default(); |
302 | let proc_macro = vec![]; | 281 | let proc_macro = vec![]; |
282 | let crate_name = CrateName::new(&sysroot[krate].name) | ||
283 | .expect("Sysroot crate names should not contain dashes"); | ||
303 | 284 | ||
304 | let crate_id = crate_graph.add_crate_root( | 285 | let crate_id = crate_graph.add_crate_root( |
305 | file_id, | 286 | file_id, |
306 | Edition::Edition2018, | 287 | Edition::Edition2018, |
307 | Some( | 288 | Some(crate_name), |
308 | CrateName::new(&sysroot[krate].name) | ||
309 | .expect("Sysroot crate names should not contain dashes"), | ||
310 | ), | ||
311 | cfg_options, | 289 | cfg_options, |
312 | env, | 290 | env, |
313 | extern_source, | 291 | extern_source, |
314 | proc_macro, | 292 | proc_macro, |
315 | ); | 293 | ); |
316 | sysroot_crates.insert(krate, crate_id); | 294 | Some((krate, crate_id)) |
317 | } | 295 | }) |
318 | } | 296 | .collect(); |
297 | |||
319 | for from in sysroot.crates() { | 298 | for from in sysroot.crates() { |
320 | for &to in sysroot[from].deps.iter() { | 299 | for &to in sysroot[from].deps.iter() { |
321 | let name = &sysroot[to].name; | 300 | let name = &sysroot[to].name; |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index dbb9c8a9b..f39559e9e 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -22,7 +22,8 @@ pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { | |||
22 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { | 22 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { |
23 | path_from_text(&format!("{}::{}", qual, segment)) | 23 | path_from_text(&format!("{}::{}", qual, segment)) |
24 | } | 24 | } |
25 | fn path_from_text(text: &str) -> ast::Path { | 25 | |
26 | pub fn path_from_text(text: &str) -> ast::Path { | ||
26 | ast_from_text(text) | 27 | ast_from_text(text) |
27 | } | 28 | } |
28 | 29 | ||
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 2c0bde920..69133e4e4 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -36,8 +36,7 @@ pub(crate) fn load_cargo( | |||
36 | extern_dirs.extend(ws.out_dirs()); | 36 | extern_dirs.extend(ws.out_dirs()); |
37 | 37 | ||
38 | let mut project_roots = ws.to_roots(); | 38 | let mut project_roots = ws.to_roots(); |
39 | project_roots | 39 | project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member)); |
40 | .extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false))); | ||
41 | 40 | ||
42 | let (sender, receiver) = unbounded(); | 41 | let (sender, receiver) = unbounded(); |
43 | let sender = Box::new(move |t| sender.send(t).unwrap()); | 42 | let sender = Box::new(move |t| sender.send(t).unwrap()); |
@@ -46,7 +45,7 @@ pub(crate) fn load_cargo( | |||
46 | .iter() | 45 | .iter() |
47 | .map(|pkg_root| { | 46 | .map(|pkg_root| { |
48 | RootEntry::new( | 47 | RootEntry::new( |
49 | pkg_root.path().clone(), | 48 | pkg_root.path().to_owned(), |
50 | RustPackageFilterBuilder::default() | 49 | RustPackageFilterBuilder::default() |
51 | .set_member(pkg_root.is_member()) | 50 | .set_member(pkg_root.is_member()) |
52 | .into_vfs_filter(), | 51 | .into_vfs_filter(), |
@@ -58,12 +57,12 @@ pub(crate) fn load_cargo( | |||
58 | ); | 57 | ); |
59 | 58 | ||
60 | let source_roots = roots | 59 | let source_roots = roots |
61 | .iter() | 60 | .into_iter() |
62 | .map(|&vfs_root| { | 61 | .map(|vfs_root| { |
63 | let source_root_id = vfs_root_to_id(vfs_root); | 62 | let source_root_id = vfs_root_to_id(vfs_root); |
64 | let project_root = project_roots | 63 | let project_root = project_roots |
65 | .iter() | 64 | .iter() |
66 | .find(|it| it.path() == &vfs.root2path(vfs_root)) | 65 | .find(|it| it.path() == vfs.root2path(vfs_root)) |
67 | .unwrap() | 66 | .unwrap() |
68 | .clone(); | 67 | .clone(); |
69 | (source_root_id, project_root) | 68 | (source_root_id, project_root) |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3c8f55f1e..04f5bb473 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -16,21 +16,33 @@ use serde::Deserialize; | |||
16 | #[derive(Debug, Clone)] | 16 | #[derive(Debug, Clone)] |
17 | pub struct Config { | 17 | pub struct Config { |
18 | pub client_caps: ClientCapsConfig, | 18 | pub client_caps: ClientCapsConfig, |
19 | pub publish_decorations: bool, | 19 | |
20 | pub with_sysroot: bool, | ||
20 | pub publish_diagnostics: bool, | 21 | pub publish_diagnostics: bool, |
22 | pub lru_capacity: Option<usize>, | ||
23 | pub proc_macro_srv: Option<String>, | ||
24 | pub files: FilesConfig, | ||
21 | pub notifications: NotificationsConfig, | 25 | pub notifications: NotificationsConfig, |
26 | |||
27 | pub cargo: CargoConfig, | ||
28 | pub rustfmt: RustfmtConfig, | ||
29 | pub check: Option<FlycheckConfig>, | ||
30 | |||
22 | pub inlay_hints: InlayHintsConfig, | 31 | pub inlay_hints: InlayHintsConfig, |
23 | pub completion: CompletionConfig, | 32 | pub completion: CompletionConfig, |
24 | pub call_info_full: bool, | 33 | pub call_info_full: bool, |
25 | pub rustfmt: RustfmtConfig, | 34 | } |
26 | pub check: Option<FlycheckConfig>, | 35 | |
27 | pub vscode_lldb: bool, | 36 | #[derive(Debug, Clone)] |
28 | pub proc_macro_srv: Option<String>, | 37 | pub struct FilesConfig { |
29 | pub lru_capacity: Option<usize>, | 38 | pub watcher: FilesWatcher, |
30 | pub use_client_watching: bool, | 39 | pub exclude: Vec<String>, |
31 | pub exclude_globs: Vec<String>, | 40 | } |
32 | pub cargo: CargoConfig, | 41 | |
33 | pub with_sysroot: bool, | 42 | #[derive(Debug, Clone)] |
43 | pub enum FilesWatcher { | ||
44 | Client, | ||
45 | Notify, | ||
34 | } | 46 | } |
35 | 47 | ||
36 | #[derive(Debug, Clone)] | 48 | #[derive(Debug, Clone)] |
@@ -60,13 +72,26 @@ pub struct ClientCapsConfig { | |||
60 | impl Default for Config { | 72 | impl Default for Config { |
61 | fn default() -> Self { | 73 | fn default() -> Self { |
62 | Config { | 74 | Config { |
63 | publish_decorations: false, | 75 | client_caps: ClientCapsConfig::default(), |
76 | |||
77 | with_sysroot: true, | ||
64 | publish_diagnostics: true, | 78 | publish_diagnostics: true, |
79 | lru_capacity: None, | ||
80 | proc_macro_srv: None, | ||
81 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, | ||
65 | notifications: NotificationsConfig { | 82 | notifications: NotificationsConfig { |
66 | workspace_loaded: true, | 83 | workspace_loaded: true, |
67 | cargo_toml_not_found: true, | 84 | cargo_toml_not_found: true, |
68 | }, | 85 | }, |
69 | client_caps: ClientCapsConfig::default(), | 86 | |
87 | cargo: CargoConfig::default(), | ||
88 | rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, | ||
89 | check: Some(FlycheckConfig::CargoCommand { | ||
90 | command: "check".to_string(), | ||
91 | all_targets: true, | ||
92 | extra_args: Vec::new(), | ||
93 | }), | ||
94 | |||
70 | inlay_hints: InlayHintsConfig { | 95 | inlay_hints: InlayHintsConfig { |
71 | type_hints: true, | 96 | type_hints: true, |
72 | parameter_hints: true, | 97 | parameter_hints: true, |
@@ -79,19 +104,6 @@ impl Default for Config { | |||
79 | add_call_argument_snippets: true, | 104 | add_call_argument_snippets: true, |
80 | }, | 105 | }, |
81 | call_info_full: true, | 106 | call_info_full: true, |
82 | rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, | ||
83 | check: Some(FlycheckConfig::CargoCommand { | ||
84 | command: "check".to_string(), | ||
85 | all_targets: true, | ||
86 | extra_args: Vec::new(), | ||
87 | }), | ||
88 | vscode_lldb: false, | ||
89 | proc_macro_srv: None, | ||
90 | lru_capacity: None, | ||
91 | use_client_watching: false, | ||
92 | exclude_globs: Vec::new(), | ||
93 | cargo: CargoConfig::default(), | ||
94 | with_sysroot: true, | ||
95 | } | 107 | } |
96 | } | 108 | } |
97 | } | 109 | } |
@@ -105,46 +117,61 @@ impl Config { | |||
105 | *self = Default::default(); | 117 | *self = Default::default(); |
106 | self.client_caps = client_caps; | 118 | self.client_caps = client_caps; |
107 | 119 | ||
108 | set(value, "/publishDecorations", &mut self.publish_decorations); | 120 | set(value, "/withSysroot", &mut self.with_sysroot); |
109 | set(value, "/excludeGlobs", &mut self.exclude_globs); | 121 | set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics); |
110 | set(value, "/useClientWatching", &mut self.use_client_watching); | ||
111 | set(value, "/lruCapacity", &mut self.lru_capacity); | 122 | set(value, "/lruCapacity", &mut self.lru_capacity); |
112 | 123 | if let Some(watcher) = get::<String>(value, "/files/watcher") { | |
113 | set(value, "/inlayHintsType", &mut self.inlay_hints.type_hints); | 124 | self.files.watcher = match watcher.as_str() { |
114 | set(value, "/inlayHintsParameter", &mut self.inlay_hints.parameter_hints); | 125 | "client" => FilesWatcher::Client, |
115 | set(value, "/inlayHintsChaining", &mut self.inlay_hints.chaining_hints); | 126 | "notify"| _ => FilesWatcher::Notify, |
116 | set(value, "/inlayHintsMaxLength", &mut self.inlay_hints.max_length); | 127 | } |
117 | 128 | } | |
118 | if let Some(false) = get(value, "cargo_watch_enable") { | 129 | set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded); |
130 | set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found); | ||
131 | |||
132 | set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features); | ||
133 | set(value, "/cargo/allFeatures", &mut self.cargo.all_features); | ||
134 | set(value, "/cargo/features", &mut self.cargo.features); | ||
135 | set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); | ||
136 | if let Some(mut args) = get::<Vec<String>>(value, "/rustfmt/overrideCommand") { | ||
137 | if !args.is_empty() { | ||
138 | let command = args.remove(0); | ||
139 | self.rustfmt = RustfmtConfig::CustomCommand { | ||
140 | command, | ||
141 | args, | ||
142 | } | ||
143 | } | ||
144 | } else if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt { | ||
145 | set(value, "/rustfmt/extraArgs", extra_args); | ||
146 | } | ||
147 | if let Some(false) = get(value, "/checkOnSave/enable") { | ||
119 | self.check = None | 148 | self.check = None |
120 | } else { | 149 | } else { |
121 | if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check | 150 | if let Some(mut args) = get::<Vec<String>>(value, "/checkOnSave/overrideCommand") { |
151 | if !args.is_empty() { | ||
152 | let command = args.remove(0); | ||
153 | self.check = Some(FlycheckConfig::CustomCommand { | ||
154 | command, | ||
155 | args, | ||
156 | }) | ||
157 | } | ||
158 | |||
159 | } else if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check | ||
122 | { | 160 | { |
123 | set(value, "/cargoWatchArgs", extra_args); | 161 | set(value, "/checkOnSave/extraArgs", extra_args); |
124 | set(value, "/cargoWatchCommand", command); | 162 | set(value, "/checkOnSave/command", command); |
125 | set(value, "/cargoWatchAllTargets", all_targets); | 163 | set(value, "/checkOnSave/allTargets", all_targets); |
126 | } | 164 | } |
127 | }; | 165 | }; |
128 | 166 | ||
129 | set(value, "/withSysroot", &mut self.with_sysroot); | 167 | set(value, "/inlayHints/typeHints", &mut self.inlay_hints.type_hints); |
130 | if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt { | 168 | set(value, "/inlayHints/parameterHints", &mut self.inlay_hints.parameter_hints); |
131 | set(value, "/rustfmtArgs", extra_args); | 169 | set(value, "/inlayHints/chainingHints", &mut self.inlay_hints.chaining_hints); |
132 | } | 170 | set(value, "/inlayHints/maxLength", &mut self.inlay_hints.max_length); |
133 | 171 | set(value, "/completion/postfix/enable", &mut self.completion.enable_postfix_completions); | |
134 | set(value, "/cargoFeatures/noDefaultFeatures", &mut self.cargo.no_default_features); | 172 | set(value, "/completion/addCallParenthesis", &mut self.completion.add_call_parenthesis); |
135 | set(value, "/cargoFeatures/allFeatures", &mut self.cargo.all_features); | 173 | set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets); |
136 | set(value, "/cargoFeatures/features", &mut self.cargo.features); | 174 | set(value, "/callInfo/full", &mut self.call_info_full); |
137 | set(value, "/cargoFeatures/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); | ||
138 | |||
139 | set(value, "/vscodeLldb", &mut self.vscode_lldb); | ||
140 | |||
141 | set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics); | ||
142 | set(value, "/featureFlags/notifications.workspace-loaded", &mut self.notifications.workspace_loaded); | ||
143 | set(value, "/featureFlags/notifications.cargo-toml-not-found", &mut self.notifications.cargo_toml_not_found); | ||
144 | set(value, "/featureFlags/completion.enable-postfix", &mut self.completion.enable_postfix_completions); | ||
145 | set(value, "/featureFlags/completion.insertion.add-call-parenthesis", &mut self.completion.add_call_parenthesis); | ||
146 | set(value, "/featureFlags/completion.insertion.add-argument-snippets", &mut self.completion.add_call_argument_snippets); | ||
147 | set(value, "/featureFlags/call-info.full", &mut self.call_info_full); | ||
148 | 175 | ||
149 | log::info!("Config::update() = {:#?}", self); | 176 | log::info!("Config::update() = {:#?}", self); |
150 | 177 | ||
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 45ae0ad9d..8d1429196 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -23,6 +23,7 @@ use lsp_types::{ | |||
23 | use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; | 23 | use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; |
24 | use ra_ide::{Canceled, FileId, LibraryData, SourceRootId}; | 24 | use ra_ide::{Canceled, FileId, LibraryData, SourceRootId}; |
25 | use ra_prof::profile; | 25 | use ra_prof::profile; |
26 | use ra_project_model::{PackageRoot, ProjectWorkspace}; | ||
26 | use ra_vfs::{VfsFile, VfsTask, Watch}; | 27 | use ra_vfs::{VfsFile, VfsTask, Watch}; |
27 | use relative_path::RelativePathBuf; | 28 | use relative_path::RelativePathBuf; |
28 | use rustc_hash::FxHashSet; | 29 | use rustc_hash::FxHashSet; |
@@ -30,7 +31,7 @@ use serde::{de::DeserializeOwned, Serialize}; | |||
30 | use threadpool::ThreadPool; | 31 | use threadpool::ThreadPool; |
31 | 32 | ||
32 | use crate::{ | 33 | use crate::{ |
33 | config::Config, | 34 | config::{Config, FilesWatcher}, |
34 | diagnostics::DiagnosticTask, | 35 | diagnostics::DiagnosticTask, |
35 | main_loop::{ | 36 | main_loop::{ |
36 | pending_requests::{PendingRequest, PendingRequests}, | 37 | pending_requests::{PendingRequest, PendingRequests}, |
@@ -40,7 +41,6 @@ use crate::{ | |||
40 | world::{WorldSnapshot, WorldState}, | 41 | world::{WorldSnapshot, WorldState}, |
41 | Result, | 42 | Result, |
42 | }; | 43 | }; |
43 | use req::ConfigurationParams; | ||
44 | 44 | ||
45 | #[derive(Debug)] | 45 | #[derive(Debug)] |
46 | pub struct LspError { | 46 | pub struct LspError { |
@@ -122,17 +122,18 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) | |||
122 | }; | 122 | }; |
123 | 123 | ||
124 | let globs = config | 124 | let globs = config |
125 | .exclude_globs | 125 | .files |
126 | .exclude | ||
126 | .iter() | 127 | .iter() |
127 | .map(|glob| crate::vfs_glob::Glob::new(glob)) | 128 | .map(|glob| crate::vfs_glob::Glob::new(glob)) |
128 | .collect::<std::result::Result<Vec<_>, _>>()?; | 129 | .collect::<std::result::Result<Vec<_>, _>>()?; |
129 | 130 | ||
130 | if config.use_client_watching { | 131 | if let FilesWatcher::Client = config.files.watcher { |
131 | let registration_options = req::DidChangeWatchedFilesRegistrationOptions { | 132 | let registration_options = req::DidChangeWatchedFilesRegistrationOptions { |
132 | watchers: workspaces | 133 | watchers: workspaces |
133 | .iter() | 134 | .iter() |
134 | .flat_map(|ws| ws.to_roots()) | 135 | .flat_map(ProjectWorkspace::to_roots) |
135 | .filter(|root| root.is_member()) | 136 | .filter(PackageRoot::is_member) |
136 | .map(|root| format!("{}/**/*.rs", root.path().display())) | 137 | .map(|root| format!("{}/**/*.rs", root.path().display())) |
137 | .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) | 138 | .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) |
138 | .collect(), | 139 | .collect(), |
@@ -153,7 +154,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) | |||
153 | workspaces, | 154 | workspaces, |
154 | config.lru_capacity, | 155 | config.lru_capacity, |
155 | &globs, | 156 | &globs, |
156 | Watch(!config.use_client_watching), | 157 | Watch(matches!(config.files.watcher, FilesWatcher::Notify)), |
157 | config, | 158 | config, |
158 | ) | 159 | ) |
159 | }; | 160 | }; |
@@ -250,9 +251,7 @@ impl fmt::Debug for Event { | |||
250 | } | 251 | } |
251 | } | 252 | } |
252 | Event::Task(Task::Notify(not)) => { | 253 | Event::Task(Task::Notify(not)) => { |
253 | if notification_is::<req::PublishDecorations>(not) | 254 | if notification_is::<req::PublishDiagnostics>(not) { |
254 | || notification_is::<req::PublishDiagnostics>(not) | ||
255 | { | ||
256 | return debug_verbose_not(not, f); | 255 | return debug_verbose_not(not, f); |
257 | } | 256 | } |
258 | } | 257 | } |
@@ -427,7 +426,6 @@ fn loop_turn( | |||
427 | update_file_notifications_on_threadpool( | 426 | update_file_notifications_on_threadpool( |
428 | pool, | 427 | pool, |
429 | world_state.snapshot(), | 428 | world_state.snapshot(), |
430 | world_state.config.publish_decorations, | ||
431 | task_sender.clone(), | 429 | task_sender.clone(), |
432 | loop_state.subscriptions.subscriptions(), | 430 | loop_state.subscriptions.subscriptions(), |
433 | ) | 431 | ) |
@@ -508,7 +506,6 @@ fn on_request( | |||
508 | .on::<req::GotoTypeDefinition>(handlers::handle_goto_type_definition)? | 506 | .on::<req::GotoTypeDefinition>(handlers::handle_goto_type_definition)? |
509 | .on::<req::ParentModule>(handlers::handle_parent_module)? | 507 | .on::<req::ParentModule>(handlers::handle_parent_module)? |
510 | .on::<req::Runnables>(handlers::handle_runnables)? | 508 | .on::<req::Runnables>(handlers::handle_runnables)? |
511 | .on::<req::DecorationsRequest>(handlers::handle_decorations)? | ||
512 | .on::<req::Completion>(handlers::handle_completion)? | 509 | .on::<req::Completion>(handlers::handle_completion)? |
513 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? | 510 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? |
514 | .on::<req::CodeLensRequest>(handlers::handle_code_lens)? | 511 | .on::<req::CodeLensRequest>(handlers::handle_code_lens)? |
@@ -611,7 +608,12 @@ fn on_notification( | |||
611 | let request_id = loop_state.next_request_id(); | 608 | let request_id = loop_state.next_request_id(); |
612 | let request = request_new::<req::WorkspaceConfiguration>( | 609 | let request = request_new::<req::WorkspaceConfiguration>( |
613 | request_id.clone(), | 610 | request_id.clone(), |
614 | ConfigurationParams::default(), | 611 | req::ConfigurationParams { |
612 | items: vec![req::ConfigurationItem { | ||
613 | scope_uri: None, | ||
614 | section: Some("rust-analyzer".to_string()), | ||
615 | }], | ||
616 | }, | ||
615 | ); | 617 | ); |
616 | msg_sender.send(request.into())?; | 618 | msg_sender.send(request.into())?; |
617 | loop_state.configuration_request_id = Some(request_id); | 619 | loop_state.configuration_request_id = Some(request_id); |
@@ -884,15 +886,13 @@ where | |||
884 | fn update_file_notifications_on_threadpool( | 886 | fn update_file_notifications_on_threadpool( |
885 | pool: &ThreadPool, | 887 | pool: &ThreadPool, |
886 | world: WorldSnapshot, | 888 | world: WorldSnapshot, |
887 | publish_decorations: bool, | ||
888 | task_sender: Sender<Task>, | 889 | task_sender: Sender<Task>, |
889 | subscriptions: Vec<FileId>, | 890 | subscriptions: Vec<FileId>, |
890 | ) { | 891 | ) { |
891 | log::trace!("updating notifications for {:?}", subscriptions); | 892 | log::trace!("updating notifications for {:?}", subscriptions); |
892 | let publish_diagnostics = world.config.publish_diagnostics; | 893 | if world.config.publish_diagnostics { |
893 | pool.execute(move || { | 894 | pool.execute(move || { |
894 | for file_id in subscriptions { | 895 | for file_id in subscriptions { |
895 | if publish_diagnostics { | ||
896 | match handlers::publish_diagnostics(&world, file_id) { | 896 | match handlers::publish_diagnostics(&world, file_id) { |
897 | Err(e) => { | 897 | Err(e) => { |
898 | if !is_canceled(&e) { | 898 | if !is_canceled(&e) { |
@@ -904,21 +904,8 @@ fn update_file_notifications_on_threadpool( | |||
904 | } | 904 | } |
905 | } | 905 | } |
906 | } | 906 | } |
907 | if publish_decorations { | 907 | }) |
908 | match handlers::publish_decorations(&world, file_id) { | 908 | } |
909 | Err(e) => { | ||
910 | if !is_canceled(&e) { | ||
911 | log::error!("failed to compute decorations: {:?}", e); | ||
912 | } | ||
913 | } | ||
914 | Ok(params) => { | ||
915 | let not = notification_new::<req::PublishDecorations>(params); | ||
916 | task_sender.send(Task::Notify(not)).unwrap(); | ||
917 | } | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | }); | ||
922 | } | 909 | } |
923 | 910 | ||
924 | pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) { | 911 | pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) { |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 23e48c089..b207f0764 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | }, | 38 | }, |
39 | diagnostics::DiagnosticTask, | 39 | diagnostics::DiagnosticTask, |
40 | from_json, | 40 | from_json, |
41 | req::{self, Decoration, InlayHint, InlayHintsParams}, | 41 | req::{self, InlayHint, InlayHintsParams}, |
42 | semantic_tokens::SemanticTokensBuilder, | 42 | semantic_tokens::SemanticTokensBuilder, |
43 | world::WorldSnapshot, | 43 | world::WorldSnapshot, |
44 | LspError, Result, | 44 | LspError, Result, |
@@ -389,15 +389,6 @@ pub fn handle_runnables( | |||
389 | Ok(res) | 389 | Ok(res) |
390 | } | 390 | } |
391 | 391 | ||
392 | pub fn handle_decorations( | ||
393 | world: WorldSnapshot, | ||
394 | params: TextDocumentIdentifier, | ||
395 | ) -> Result<Vec<Decoration>> { | ||
396 | let _p = profile("handle_decorations"); | ||
397 | let file_id = params.try_conv_with(&world)?; | ||
398 | highlight(&world, file_id) | ||
399 | } | ||
400 | |||
401 | pub fn handle_completion( | 392 | pub fn handle_completion( |
402 | world: WorldSnapshot, | 393 | world: WorldSnapshot, |
403 | params: req::CompletionParams, | 394 | params: req::CompletionParams, |
@@ -819,23 +810,21 @@ pub fn handle_code_lens( | |||
819 | }; | 810 | }; |
820 | lenses.push(lens); | 811 | lenses.push(lens); |
821 | 812 | ||
822 | if world.config.vscode_lldb { | 813 | if r.args[0] == "run" { |
823 | if r.args[0] == "run" { | 814 | r.args[0] = "build".into(); |
824 | r.args[0] = "build".into(); | 815 | } else { |
825 | } else { | 816 | r.args.push("--no-run".into()); |
826 | r.args.push("--no-run".into()); | ||
827 | } | ||
828 | let debug_lens = CodeLens { | ||
829 | range: r.range, | ||
830 | command: Some(Command { | ||
831 | title: "Debug".into(), | ||
832 | command: "rust-analyzer.debugSingle".into(), | ||
833 | arguments: Some(vec![to_value(r).unwrap()]), | ||
834 | }), | ||
835 | data: None, | ||
836 | }; | ||
837 | lenses.push(debug_lens); | ||
838 | } | 817 | } |
818 | let debug_lens = CodeLens { | ||
819 | range: r.range, | ||
820 | command: Some(Command { | ||
821 | title: "Debug".into(), | ||
822 | command: "rust-analyzer.debugSingle".into(), | ||
823 | arguments: Some(vec![to_value(r).unwrap()]), | ||
824 | }), | ||
825 | data: None, | ||
826 | }; | ||
827 | lenses.push(debug_lens); | ||
839 | } | 828 | } |
840 | 829 | ||
841 | // Handle impls | 830 | // Handle impls |
@@ -970,15 +959,6 @@ pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<Dia | |||
970 | Ok(DiagnosticTask::SetNative(file_id, diagnostics)) | 959 | Ok(DiagnosticTask::SetNative(file_id, diagnostics)) |
971 | } | 960 | } |
972 | 961 | ||
973 | pub fn publish_decorations( | ||
974 | world: &WorldSnapshot, | ||
975 | file_id: FileId, | ||
976 | ) -> Result<req::PublishDecorationsParams> { | ||
977 | let _p = profile("publish_decorations"); | ||
978 | let uri = world.file_id_to_uri(file_id)?; | ||
979 | Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? }) | ||
980 | } | ||
981 | |||
982 | fn to_lsp_runnable( | 962 | fn to_lsp_runnable( |
983 | world: &WorldSnapshot, | 963 | world: &WorldSnapshot, |
984 | file_id: FileId, | 964 | file_id: FileId, |
@@ -1008,21 +988,6 @@ fn to_lsp_runnable( | |||
1008 | }) | 988 | }) |
1009 | } | 989 | } |
1010 | 990 | ||
1011 | fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> { | ||
1012 | let line_index = world.analysis().file_line_index(file_id)?; | ||
1013 | let res = world | ||
1014 | .analysis() | ||
1015 | .highlight(file_id)? | ||
1016 | .into_iter() | ||
1017 | .map(|h| Decoration { | ||
1018 | range: h.range.conv_with(&line_index), | ||
1019 | tag: h.highlight.to_string(), | ||
1020 | binding_hash: h.binding_hash.map(|x| x.to_string()), | ||
1021 | }) | ||
1022 | .collect(); | ||
1023 | Ok(res) | ||
1024 | } | ||
1025 | |||
1026 | pub fn handle_inlay_hints( | 991 | pub fn handle_inlay_hints( |
1027 | world: WorldSnapshot, | 992 | world: WorldSnapshot, |
1028 | params: InlayHintsParams, | 993 | params: InlayHintsParams, |
diff --git a/crates/rust-analyzer/src/main_loop/subscriptions.rs b/crates/rust-analyzer/src/main_loop/subscriptions.rs index bee6437cf..2c76418be 100644 --- a/crates/rust-analyzer/src/main_loop/subscriptions.rs +++ b/crates/rust-analyzer/src/main_loop/subscriptions.rs | |||
@@ -17,6 +17,6 @@ impl Subscriptions { | |||
17 | self.subs.remove(&file_id); | 17 | self.subs.remove(&file_id); |
18 | } | 18 | } |
19 | pub(crate) fn subscriptions(&self) -> Vec<FileId> { | 19 | pub(crate) fn subscriptions(&self) -> Vec<FileId> { |
20 | self.subs.iter().cloned().collect() | 20 | self.subs.iter().copied().collect() |
21 | } | 21 | } |
22 | } | 22 | } |
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs index 994f0ed61..b8b627e28 100644 --- a/crates/rust-analyzer/src/req.rs +++ b/crates/rust-analyzer/src/req.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! Defines `rust-analyzer` specific custom messages. | 1 | //! Defines `rust-analyzer` specific custom messages. |
2 | 2 | ||
3 | use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; | 3 | use lsp_types::{Location, Position, Range, TextDocumentIdentifier}; |
4 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
5 | use serde::{Deserialize, Serialize}; | 5 | use serde::{Deserialize, Serialize}; |
6 | 6 | ||
7 | pub use lsp_types::{ | 7 | pub use lsp_types::{ |
8 | notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, | 8 | notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, |
9 | CodeLensParams, CompletionParams, CompletionResponse, ConfigurationParams, DiagnosticTag, | 9 | CodeLensParams, CompletionParams, CompletionResponse, ConfigurationItem, ConfigurationParams, |
10 | DidChangeConfigurationParams, DidChangeWatchedFilesParams, | 10 | DiagnosticTag, DidChangeConfigurationParams, DidChangeWatchedFilesParams, |
11 | DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams, | 11 | DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams, |
12 | DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType, | 12 | DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType, |
13 | PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken, | 13 | PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken, |
@@ -86,36 +86,6 @@ pub struct FindMatchingBraceParams { | |||
86 | pub offsets: Vec<Position>, | 86 | pub offsets: Vec<Position>, |
87 | } | 87 | } |
88 | 88 | ||
89 | pub enum DecorationsRequest {} | ||
90 | |||
91 | impl Request for DecorationsRequest { | ||
92 | type Params = TextDocumentIdentifier; | ||
93 | type Result = Vec<Decoration>; | ||
94 | const METHOD: &'static str = "rust-analyzer/decorationsRequest"; | ||
95 | } | ||
96 | |||
97 | pub enum PublishDecorations {} | ||
98 | |||
99 | impl Notification for PublishDecorations { | ||
100 | type Params = PublishDecorationsParams; | ||
101 | const METHOD: &'static str = "rust-analyzer/publishDecorations"; | ||
102 | } | ||
103 | |||
104 | #[derive(Deserialize, Serialize, Debug)] | ||
105 | #[serde(rename_all = "camelCase")] | ||
106 | pub struct PublishDecorationsParams { | ||
107 | pub uri: Url, | ||
108 | pub decorations: Vec<Decoration>, | ||
109 | } | ||
110 | |||
111 | #[derive(Deserialize, Serialize, Debug)] | ||
112 | #[serde(rename_all = "camelCase")] | ||
113 | pub struct Decoration { | ||
114 | pub range: Range, | ||
115 | pub tag: String, | ||
116 | pub binding_hash: Option<String>, | ||
117 | } | ||
118 | |||
119 | pub enum ParentModule {} | 89 | pub enum ParentModule {} |
120 | 90 | ||
121 | impl Request for ParentModule { | 91 | impl Request for ParentModule { |
diff --git a/crates/rust-analyzer/src/vfs_glob.rs b/crates/rust-analyzer/src/vfs_glob.rs index 91b33f94e..ff37a7008 100644 --- a/crates/rust-analyzer/src/vfs_glob.rs +++ b/crates/rust-analyzer/src/vfs_glob.rs | |||
@@ -29,10 +29,14 @@ impl RustPackageFilterBuilder { | |||
29 | self.is_member = is_member; | 29 | self.is_member = is_member; |
30 | self | 30 | self |
31 | } | 31 | } |
32 | pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder { | 32 | |
33 | self.exclude.add(glob); | 33 | pub fn exclude(mut self, globs: impl IntoIterator<Item = Glob>) -> RustPackageFilterBuilder { |
34 | for glob in globs.into_iter() { | ||
35 | self.exclude.add(glob); | ||
36 | } | ||
34 | self | 37 | self |
35 | } | 38 | } |
39 | |||
36 | pub fn into_vfs_filter(self) -> Box<dyn Filter> { | 40 | pub fn into_vfs_filter(self) -> Box<dyn Filter> { |
37 | let RustPackageFilterBuilder { is_member, mut exclude } = self; | 41 | let RustPackageFilterBuilder { is_member, mut exclude } = self; |
38 | for &glob in ALWAYS_IGNORED { | 42 | for &glob in ALWAYS_IGNORED { |
@@ -87,7 +91,7 @@ fn test_globs() { | |||
87 | 91 | ||
88 | let filter = RustPackageFilterBuilder::default() | 92 | let filter = RustPackageFilterBuilder::default() |
89 | .set_member(true) | 93 | .set_member(true) |
90 | .exclude(Glob::new("src/llvm-project/**").unwrap()) | 94 | .exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap())) |
91 | .into_vfs_filter(); | 95 | .into_vfs_filter(); |
92 | 96 | ||
93 | assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); | 97 | assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); |
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 5674f42ef..365f57d8c 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -87,44 +87,35 @@ impl WorldState { | |||
87 | ) -> WorldState { | 87 | ) -> WorldState { |
88 | let mut change = AnalysisChange::new(); | 88 | let mut change = AnalysisChange::new(); |
89 | 89 | ||
90 | let mut roots = Vec::new(); | 90 | let extern_dirs: FxHashSet<_> = |
91 | roots.extend(folder_roots.iter().map(|path| { | 91 | workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect(); |
92 | let mut filter = RustPackageFilterBuilder::default().set_member(true); | 92 | |
93 | for glob in exclude_globs.iter() { | 93 | let roots: Vec<_> = { |
94 | filter = filter.exclude(glob.clone()); | 94 | let create_filter = |is_member| { |
95 | } | 95 | RustPackageFilterBuilder::default() |
96 | RootEntry::new(path.clone(), filter.into_vfs_filter()) | 96 | .set_member(is_member) |
97 | })); | 97 | .exclude(exclude_globs.iter().cloned()) |
98 | for ws in workspaces.iter() { | 98 | .into_vfs_filter() |
99 | roots.extend(ws.to_roots().into_iter().map(|pkg_root| { | 99 | }; |
100 | let mut filter = | 100 | folder_roots |
101 | RustPackageFilterBuilder::default().set_member(pkg_root.is_member()); | 101 | .iter() |
102 | for glob in exclude_globs.iter() { | 102 | .map(|path| RootEntry::new(path.clone(), create_filter(true))) |
103 | filter = filter.exclude(glob.clone()); | 103 | .chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| { |
104 | } | 104 | RootEntry::new(pkg_root.path().to_owned(), create_filter(pkg_root.is_member())) |
105 | RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) | 105 | })) |
106 | })); | 106 | .chain( |
107 | } | 107 | extern_dirs |
108 | 108 | .iter() | |
109 | let mut extern_dirs = FxHashSet::default(); | 109 | .map(|path| RootEntry::new(path.to_owned(), create_filter(false))), |
110 | for ws in workspaces.iter() { | 110 | ) |
111 | extern_dirs.extend(ws.out_dirs()); | 111 | .collect() |
112 | } | 112 | }; |
113 | |||
114 | let mut extern_source_roots = FxHashMap::default(); | ||
115 | |||
116 | roots.extend(extern_dirs.iter().map(|path| { | ||
117 | let mut filter = RustPackageFilterBuilder::default().set_member(false); | ||
118 | for glob in exclude_globs.iter() { | ||
119 | filter = filter.exclude(glob.clone()); | ||
120 | } | ||
121 | RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter()) | ||
122 | })); | ||
123 | 113 | ||
124 | let (task_sender, task_receiver) = unbounded(); | 114 | let (task_sender, task_receiver) = unbounded(); |
125 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); | 115 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); |
126 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); | 116 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); |
127 | 117 | ||
118 | let mut extern_source_roots = FxHashMap::default(); | ||
128 | for r in vfs_roots { | 119 | for r in vfs_roots { |
129 | let vfs_root_path = vfs.root2path(r); | 120 | let vfs_root_path = vfs.root2path(r); |
130 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); | 121 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); |