diff options
Diffstat (limited to 'crates')
34 files changed, 503 insertions, 100 deletions
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 62dcb3808..543224232 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -623,6 +623,30 @@ fn process(map: HashMap<String, String>) {} | |||
623 | } | 623 | } |
624 | 624 | ||
625 | #[test] | 625 | #[test] |
626 | fn doctest_replace_unwrap_with_match() { | ||
627 | check( | ||
628 | "replace_unwrap_with_match", | ||
629 | r#####" | ||
630 | enum Result<T, E> { Ok(T), Err(E) } | ||
631 | fn main() { | ||
632 | let x: Result<i32, i32> = Result::Ok(92); | ||
633 | let y = x.<|>unwrap(); | ||
634 | } | ||
635 | "#####, | ||
636 | r#####" | ||
637 | enum Result<T, E> { Ok(T), Err(E) } | ||
638 | fn main() { | ||
639 | let x: Result<i32, i32> = Result::Ok(92); | ||
640 | let y = match x { | ||
641 | Ok(a) => a, | ||
642 | _ => unreachable!(), | ||
643 | }; | ||
644 | } | ||
645 | "#####, | ||
646 | ) | ||
647 | } | ||
648 | |||
649 | #[test] | ||
626 | fn doctest_split_import() { | 650 | fn doctest_split_import() { |
627 | check( | 651 | check( |
628 | "split_import", | 652 | "split_import", |
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index a63ef48b1..d86d804b2 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs | |||
@@ -130,8 +130,8 @@ mod tests { | |||
130 | fn add_explicit_type_works_for_macro_call() { | 130 | fn add_explicit_type_works_for_macro_call() { |
131 | check_assist( | 131 | check_assist( |
132 | add_explicit_type, | 132 | add_explicit_type, |
133 | "macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", | 133 | r"macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", |
134 | "macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }", | 134 | r"macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }", |
135 | ); | 135 | ); |
136 | } | 136 | } |
137 | 137 | ||
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs new file mode 100644 index 000000000..62cb7a763 --- /dev/null +++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -0,0 +1,177 @@ | |||
1 | use std::iter; | ||
2 | |||
3 | use ra_syntax::{ | ||
4 | ast::{self, make}, | ||
5 | AstNode, | ||
6 | }; | ||
7 | |||
8 | use crate::{Assist, AssistCtx, AssistId}; | ||
9 | use ast::edit::IndentLevel; | ||
10 | |||
11 | // Assist: replace_unwrap_with_match | ||
12 | // | ||
13 | // Replaces `unwrap` a `match` expression. Works for Result and Option. | ||
14 | // | ||
15 | // ``` | ||
16 | // enum Result<T, E> { Ok(T), Err(E) } | ||
17 | // fn main() { | ||
18 | // let x: Result<i32, i32> = Result::Ok(92); | ||
19 | // let y = x.<|>unwrap(); | ||
20 | // } | ||
21 | // ``` | ||
22 | // -> | ||
23 | // ``` | ||
24 | // enum Result<T, E> { Ok(T), Err(E) } | ||
25 | // fn main() { | ||
26 | // let x: Result<i32, i32> = Result::Ok(92); | ||
27 | // let y = match x { | ||
28 | // Ok(a) => a, | ||
29 | // _ => unreachable!(), | ||
30 | // }; | ||
31 | // } | ||
32 | // ``` | ||
33 | pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> { | ||
34 | let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?; | ||
35 | let name = method_call.name_ref()?; | ||
36 | if name.text() != "unwrap" { | ||
37 | return None; | ||
38 | } | ||
39 | let caller = method_call.expr()?; | ||
40 | let ty = ctx.sema.type_of_expr(&caller)?; | ||
41 | |||
42 | let type_name = ty.as_adt()?.name(ctx.sema.db).to_string(); | ||
43 | |||
44 | for (unwrap_type, variant_name) in [("Result", "Ok"), ("Option", "Some")].iter() { | ||
45 | if &type_name == unwrap_type { | ||
46 | return ctx.add_assist( | ||
47 | AssistId("replace_unwrap_with_match"), | ||
48 | "Replace unwrap with match", | ||
49 | |edit| { | ||
50 | let ok_path = | ||
51 | make::path_unqualified(make::path_segment(make::name_ref(variant_name))); | ||
52 | let it = make::bind_pat(make::name("a")).into(); | ||
53 | let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); | ||
54 | |||
55 | let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); | ||
56 | let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); | ||
57 | |||
58 | let unreachable_call = make::unreachable_macro_call().into(); | ||
59 | let err_arm = make::match_arm( | ||
60 | iter::once(make::placeholder_pat().into()), | ||
61 | unreachable_call, | ||
62 | ); | ||
63 | |||
64 | let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); | ||
65 | let match_expr = make::expr_match(caller.clone(), match_arm_list); | ||
66 | let match_expr = | ||
67 | IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); | ||
68 | |||
69 | edit.target(method_call.syntax().text_range()); | ||
70 | edit.set_cursor(caller.syntax().text_range().start()); | ||
71 | edit.replace_ast::<ast::Expr>(method_call.into(), match_expr); | ||
72 | }, | ||
73 | ); | ||
74 | } | ||
75 | } | ||
76 | None | ||
77 | } | ||
78 | |||
79 | #[cfg(test)] | ||
80 | mod tests { | ||
81 | use super::*; | ||
82 | use crate::helpers::{check_assist, check_assist_target}; | ||
83 | |||
84 | #[test] | ||
85 | fn test_replace_result_unwrap_with_match() { | ||
86 | check_assist( | ||
87 | replace_unwrap_with_match, | ||
88 | r" | ||
89 | enum Result<T, E> { Ok(T), Err(E) } | ||
90 | fn i<T>(a: T) -> T { a } | ||
91 | fn main() { | ||
92 | let x: Result<i32, i32> = Result::Ok(92); | ||
93 | let y = i(x).<|>unwrap(); | ||
94 | } | ||
95 | ", | ||
96 | r" | ||
97 | enum Result<T, E> { Ok(T), Err(E) } | ||
98 | fn i<T>(a: T) -> T { a } | ||
99 | fn main() { | ||
100 | let x: Result<i32, i32> = Result::Ok(92); | ||
101 | let y = <|>match i(x) { | ||
102 | Ok(a) => a, | ||
103 | _ => unreachable!(), | ||
104 | }; | ||
105 | } | ||
106 | ", | ||
107 | ) | ||
108 | } | ||
109 | |||
110 | #[test] | ||
111 | fn test_replace_option_unwrap_with_match() { | ||
112 | check_assist( | ||
113 | replace_unwrap_with_match, | ||
114 | r" | ||
115 | enum Option<T> { Some(T), None } | ||
116 | fn i<T>(a: T) -> T { a } | ||
117 | fn main() { | ||
118 | let x = Option::Some(92); | ||
119 | let y = i(x).<|>unwrap(); | ||
120 | } | ||
121 | ", | ||
122 | r" | ||
123 | enum Option<T> { Some(T), None } | ||
124 | fn i<T>(a: T) -> T { a } | ||
125 | fn main() { | ||
126 | let x = Option::Some(92); | ||
127 | let y = <|>match i(x) { | ||
128 | Some(a) => a, | ||
129 | _ => unreachable!(), | ||
130 | }; | ||
131 | } | ||
132 | ", | ||
133 | ); | ||
134 | } | ||
135 | |||
136 | #[test] | ||
137 | fn test_replace_result_unwrap_with_match_chaining() { | ||
138 | check_assist( | ||
139 | replace_unwrap_with_match, | ||
140 | r" | ||
141 | enum Result<T, E> { Ok(T), Err(E) } | ||
142 | fn i<T>(a: T) -> T { a } | ||
143 | fn main() { | ||
144 | let x: Result<i32, i32> = Result::Ok(92); | ||
145 | let y = i(x).<|>unwrap().count_zeroes(); | ||
146 | } | ||
147 | ", | ||
148 | r" | ||
149 | enum Result<T, E> { Ok(T), Err(E) } | ||
150 | fn i<T>(a: T) -> T { a } | ||
151 | fn main() { | ||
152 | let x: Result<i32, i32> = Result::Ok(92); | ||
153 | let y = <|>match i(x) { | ||
154 | Ok(a) => a, | ||
155 | _ => unreachable!(), | ||
156 | }.count_zeroes(); | ||
157 | } | ||
158 | ", | ||
159 | ) | ||
160 | } | ||
161 | |||
162 | #[test] | ||
163 | fn replace_unwrap_with_match_target() { | ||
164 | check_assist_target( | ||
165 | replace_unwrap_with_match, | ||
166 | r" | ||
167 | enum Option<T> { Some(T), None } | ||
168 | fn i<T>(a: T) -> T { a } | ||
169 | fn main() { | ||
170 | let x = Option::Some(92); | ||
171 | let y = i(x).<|>unwrap(); | ||
172 | } | ||
173 | ", | ||
174 | r"i(x).unwrap()", | ||
175 | ); | ||
176 | } | ||
177 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index bcc9b3f10..becd5e99d 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -119,6 +119,7 @@ mod handlers { | |||
119 | mod remove_mut; | 119 | mod remove_mut; |
120 | mod replace_if_let_with_match; | 120 | mod replace_if_let_with_match; |
121 | mod replace_qualified_name_with_use; | 121 | mod replace_qualified_name_with_use; |
122 | mod replace_unwrap_with_match; | ||
122 | mod split_import; | 123 | mod split_import; |
123 | 124 | ||
124 | pub(crate) fn all() -> &'static [AssistHandler] { | 125 | pub(crate) fn all() -> &'static [AssistHandler] { |
@@ -154,6 +155,7 @@ mod handlers { | |||
154 | remove_mut::remove_mut, | 155 | remove_mut::remove_mut, |
155 | replace_if_let_with_match::replace_if_let_with_match, | 156 | replace_if_let_with_match::replace_if_let_with_match, |
156 | replace_qualified_name_with_use::replace_qualified_name_with_use, | 157 | replace_qualified_name_with_use::replace_qualified_name_with_use, |
158 | replace_unwrap_with_match::replace_unwrap_with_match, | ||
157 | split_import::split_import, | 159 | split_import::split_import, |
158 | ] | 160 | ] |
159 | } | 161 | } |
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml index 878c22ba9..8ab409158 100644 --- a/crates/ra_db/Cargo.toml +++ b/crates/ra_db/Cargo.toml | |||
@@ -15,4 +15,5 @@ rustc-hash = "1.1.0" | |||
15 | ra_syntax = { path = "../ra_syntax" } | 15 | ra_syntax = { path = "../ra_syntax" } |
16 | ra_cfg = { path = "../ra_cfg" } | 16 | ra_cfg = { path = "../ra_cfg" } |
17 | ra_prof = { path = "../ra_prof" } | 17 | ra_prof = { path = "../ra_prof" } |
18 | ra_tt = { path = "../ra_tt" } | ||
18 | test_utils = { path = "../test_utils" } | 19 | test_utils = { path = "../test_utils" } |
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index 3464f43df..7777ce81e 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -28,9 +28,9 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
28 | db | 28 | db |
29 | } | 29 | } |
30 | 30 | ||
31 | fn with_position(fixture: &str) -> (Self, FilePosition) { | 31 | fn with_position(ra_fixture: &str) -> (Self, FilePosition) { |
32 | let mut db = Self::default(); | 32 | let mut db = Self::default(); |
33 | let pos = with_files(&mut db, fixture); | 33 | let pos = with_files(&mut db, ra_fixture); |
34 | (db, pos.unwrap()) | 34 | (db, pos.unwrap()) |
35 | } | 35 | } |
36 | 36 | ||
@@ -70,6 +70,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId | |||
70 | meta.cfg, | 70 | meta.cfg, |
71 | meta.env, | 71 | meta.env, |
72 | Default::default(), | 72 | Default::default(), |
73 | Default::default(), | ||
73 | ); | 74 | ); |
74 | crate_graph | 75 | crate_graph |
75 | } else { | 76 | } else { |
@@ -81,6 +82,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId | |||
81 | CfgOptions::default(), | 82 | CfgOptions::default(), |
82 | Env::default(), | 83 | Env::default(), |
83 | Default::default(), | 84 | Default::default(), |
85 | Default::default(), | ||
84 | ); | 86 | ); |
85 | crate_graph | 87 | crate_graph |
86 | }; | 88 | }; |
@@ -130,6 +132,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit | |||
130 | meta.cfg, | 132 | meta.cfg, |
131 | meta.env, | 133 | meta.env, |
132 | Default::default(), | 134 | Default::default(), |
135 | Default::default(), | ||
133 | ); | 136 | ); |
134 | let prev = crates.insert(krate.clone(), crate_id); | 137 | let prev = crates.insert(krate.clone(), crate_id); |
135 | assert!(prev.is_none()); | 138 | assert!(prev.is_none()); |
@@ -167,6 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit | |||
167 | CfgOptions::default(), | 170 | CfgOptions::default(), |
168 | Env::default(), | 171 | Env::default(), |
169 | Default::default(), | 172 | Default::default(), |
173 | Default::default(), | ||
170 | ); | 174 | ); |
171 | } else { | 175 | } else { |
172 | for (from, to) in crate_deps { | 176 | for (from, to) in crate_deps { |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index e371f849d..5ddce98c6 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -10,6 +10,7 @@ use std::{ | |||
10 | fmt, ops, | 10 | fmt, ops, |
11 | path::{Path, PathBuf}, | 11 | path::{Path, PathBuf}, |
12 | str::FromStr, | 12 | str::FromStr, |
13 | sync::Arc, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | use ra_cfg::CfgOptions; | 16 | use ra_cfg::CfgOptions; |
@@ -19,6 +20,7 @@ use rustc_hash::FxHashSet; | |||
19 | 20 | ||
20 | use crate::{RelativePath, RelativePathBuf}; | 21 | use crate::{RelativePath, RelativePathBuf}; |
21 | use fmt::Display; | 22 | use fmt::Display; |
23 | use ra_tt::TokenExpander; | ||
22 | 24 | ||
23 | /// `FileId` is an integer which uniquely identifies a file. File paths are | 25 | /// `FileId` is an integer which uniquely identifies a file. File paths are |
24 | /// messy and system-dependent, so most of the code should work directly with | 26 | /// messy and system-dependent, so most of the code should work directly with |
@@ -115,6 +117,22 @@ impl Display for CrateName { | |||
115 | } | 117 | } |
116 | } | 118 | } |
117 | 119 | ||
120 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
121 | pub struct ProcMacroId(pub u32); | ||
122 | |||
123 | #[derive(Debug, Clone)] | ||
124 | pub struct ProcMacro { | ||
125 | pub name: SmolStr, | ||
126 | pub expander: Arc<dyn TokenExpander>, | ||
127 | } | ||
128 | |||
129 | impl Eq for ProcMacro {} | ||
130 | impl PartialEq for ProcMacro { | ||
131 | fn eq(&self, other: &ProcMacro) -> bool { | ||
132 | self.name == other.name && Arc::ptr_eq(&self.expander, &other.expander) | ||
133 | } | ||
134 | } | ||
135 | |||
118 | #[derive(Debug, Clone, PartialEq, Eq)] | 136 | #[derive(Debug, Clone, PartialEq, Eq)] |
119 | pub struct CrateData { | 137 | pub struct CrateData { |
120 | pub root_file_id: FileId, | 138 | pub root_file_id: FileId, |
@@ -127,6 +145,7 @@ pub struct CrateData { | |||
127 | pub env: Env, | 145 | pub env: Env, |
128 | pub extern_source: ExternSource, | 146 | pub extern_source: ExternSource, |
129 | pub dependencies: Vec<Dependency>, | 147 | pub dependencies: Vec<Dependency>, |
148 | pub proc_macro: Vec<ProcMacro>, | ||
130 | } | 149 | } |
131 | 150 | ||
132 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 151 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -166,7 +185,11 @@ impl CrateGraph { | |||
166 | cfg_options: CfgOptions, | 185 | cfg_options: CfgOptions, |
167 | env: Env, | 186 | env: Env, |
168 | extern_source: ExternSource, | 187 | extern_source: ExternSource, |
188 | proc_macro: Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)>, | ||
169 | ) -> CrateId { | 189 | ) -> CrateId { |
190 | let proc_macro = | ||
191 | proc_macro.into_iter().map(|(name, it)| ProcMacro { name, expander: it }).collect(); | ||
192 | |||
170 | let data = CrateData { | 193 | let data = CrateData { |
171 | root_file_id: file_id, | 194 | root_file_id: file_id, |
172 | edition, | 195 | edition, |
@@ -174,6 +197,7 @@ impl CrateGraph { | |||
174 | cfg_options, | 197 | cfg_options, |
175 | env, | 198 | env, |
176 | extern_source, | 199 | extern_source, |
200 | proc_macro, | ||
177 | dependencies: Vec::new(), | 201 | dependencies: Vec::new(), |
178 | }; | 202 | }; |
179 | let crate_id = CrateId(self.arena.len() as u32); | 203 | let crate_id = CrateId(self.arena.len() as u32); |
@@ -345,6 +369,7 @@ mod tests { | |||
345 | CfgOptions::default(), | 369 | CfgOptions::default(), |
346 | Env::default(), | 370 | Env::default(), |
347 | Default::default(), | 371 | Default::default(), |
372 | Default::default(), | ||
348 | ); | 373 | ); |
349 | let crate2 = graph.add_crate_root( | 374 | let crate2 = graph.add_crate_root( |
350 | FileId(2u32), | 375 | FileId(2u32), |
@@ -353,6 +378,7 @@ mod tests { | |||
353 | CfgOptions::default(), | 378 | CfgOptions::default(), |
354 | Env::default(), | 379 | Env::default(), |
355 | Default::default(), | 380 | Default::default(), |
381 | Default::default(), | ||
356 | ); | 382 | ); |
357 | let crate3 = graph.add_crate_root( | 383 | let crate3 = graph.add_crate_root( |
358 | FileId(3u32), | 384 | FileId(3u32), |
@@ -361,6 +387,7 @@ mod tests { | |||
361 | CfgOptions::default(), | 387 | CfgOptions::default(), |
362 | Env::default(), | 388 | Env::default(), |
363 | Default::default(), | 389 | Default::default(), |
390 | Default::default(), | ||
364 | ); | 391 | ); |
365 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); | 392 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); |
366 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); | 393 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); |
@@ -377,6 +404,7 @@ mod tests { | |||
377 | CfgOptions::default(), | 404 | CfgOptions::default(), |
378 | Env::default(), | 405 | Env::default(), |
379 | Default::default(), | 406 | Default::default(), |
407 | Default::default(), | ||
380 | ); | 408 | ); |
381 | let crate2 = graph.add_crate_root( | 409 | let crate2 = graph.add_crate_root( |
382 | FileId(2u32), | 410 | FileId(2u32), |
@@ -385,6 +413,7 @@ mod tests { | |||
385 | CfgOptions::default(), | 413 | CfgOptions::default(), |
386 | Env::default(), | 414 | Env::default(), |
387 | Default::default(), | 415 | Default::default(), |
416 | Default::default(), | ||
388 | ); | 417 | ); |
389 | let crate3 = graph.add_crate_root( | 418 | let crate3 = graph.add_crate_root( |
390 | FileId(3u32), | 419 | FileId(3u32), |
@@ -393,6 +422,7 @@ mod tests { | |||
393 | CfgOptions::default(), | 422 | CfgOptions::default(), |
394 | Env::default(), | 423 | Env::default(), |
395 | Default::default(), | 424 | Default::default(), |
425 | Default::default(), | ||
396 | ); | 426 | ); |
397 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); | 427 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); |
398 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); | 428 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); |
@@ -408,6 +438,7 @@ mod tests { | |||
408 | CfgOptions::default(), | 438 | CfgOptions::default(), |
409 | Env::default(), | 439 | Env::default(), |
410 | Default::default(), | 440 | Default::default(), |
441 | Default::default(), | ||
411 | ); | 442 | ); |
412 | let crate2 = graph.add_crate_root( | 443 | let crate2 = graph.add_crate_root( |
413 | FileId(2u32), | 444 | FileId(2u32), |
@@ -416,6 +447,7 @@ mod tests { | |||
416 | CfgOptions::default(), | 447 | CfgOptions::default(), |
417 | Env::default(), | 448 | Env::default(), |
418 | Default::default(), | 449 | Default::default(), |
450 | Default::default(), | ||
419 | ); | 451 | ); |
420 | assert!(graph | 452 | assert!(graph |
421 | .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) | 453 | .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index bac24e218..a06f59c14 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -12,7 +12,7 @@ pub use crate::{ | |||
12 | cancellation::Canceled, | 12 | cancellation::Canceled, |
13 | input::{ | 13 | input::{ |
14 | CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, | 14 | CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, |
15 | FileId, SourceRoot, SourceRootId, | 15 | FileId, ProcMacroId, SourceRoot, SourceRootId, |
16 | }, | 16 | }, |
17 | }; | 17 | }; |
18 | pub use relative_path::{RelativePath, RelativePathBuf}; | 18 | pub use relative_path::{RelativePath, RelativePathBuf}; |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index fcba95091..ec931b34f 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -10,15 +10,16 @@ pub use hir_def::db::{ | |||
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | 10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternMacroQuery, MacroArgQuery, MacroDefQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
14 | MacroExpandQuery, ParseMacroQuery, | 14 | MacroArgQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, |
15 | }; | 15 | }; |
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, |
21 | InternTypeCtorQuery, StructDatumQuery, TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, | 21 | InternTypeCtorQuery, InternTypeParamIdQuery, StructDatumQuery, TraitDatumQuery, |
22 | TraitSolveQuery, TyQuery, ValueTyQuery, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | #[test] | 25 | #[test] |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 3cf0c66ea..e8443dde8 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -563,7 +563,8 @@ impl ExprCollector<'_> { | |||
563 | ast::ModuleItem::ImplDef(_) | 563 | ast::ModuleItem::ImplDef(_) |
564 | | ast::ModuleItem::UseItem(_) | 564 | | ast::ModuleItem::UseItem(_) |
565 | | ast::ModuleItem::ExternCrateItem(_) | 565 | | ast::ModuleItem::ExternCrateItem(_) |
566 | | ast::ModuleItem::Module(_) => continue, | 566 | | ast::ModuleItem::Module(_) |
567 | | ast::ModuleItem::MacroCall(_) => continue, | ||
567 | }; | 568 | }; |
568 | self.body.item_scope.define_def(def); | 569 | self.body.item_scope.define_def(def); |
569 | if let Some(name) = name { | 570 | if let Some(name) = name { |
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 7f8c1ea21..5dc7395f5 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs | |||
@@ -48,6 +48,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
48 | fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; | 48 | fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; |
49 | 49 | ||
50 | #[salsa::invoke(crate_def_map_wait)] | 50 | #[salsa::invoke(crate_def_map_wait)] |
51 | #[salsa::transparent] | ||
51 | fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; | 52 | fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; |
52 | 53 | ||
53 | #[salsa::invoke(CrateDefMap::crate_def_map_query)] | 54 | #[salsa::invoke(CrateDefMap::crate_def_map_query)] |
@@ -109,12 +110,6 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
109 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; | 110 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; |
110 | } | 111 | } |
111 | 112 | ||
112 | // impl<T: DefDatabase> Upcast<dyn AstDatabase> for T { | ||
113 | // fn upcast(&self) -> &dyn AstDatabase { | ||
114 | // &*self | ||
115 | // } | ||
116 | // } | ||
117 | |||
118 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 113 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { |
119 | let _p = profile("crate_def_map:wait"); | 114 | let _p = profile("crate_def_map:wait"); |
120 | db.crate_def_map_query(krate) | 115 | db.crate_def_map_query(krate) |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 9c125f32f..8fe3f8617 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -11,7 +11,7 @@ use hir_expand::{ | |||
11 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 11 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
12 | }; | 12 | }; |
13 | use ra_cfg::CfgOptions; | 13 | use ra_cfg::CfgOptions; |
14 | use ra_db::{CrateId, FileId}; | 14 | use ra_db::{CrateId, FileId, ProcMacroId}; |
15 | use ra_syntax::ast; | 15 | use ra_syntax::ast; |
16 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
17 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
@@ -53,6 +53,16 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
53 | } | 53 | } |
54 | 54 | ||
55 | let cfg_options = &crate_graph[def_map.krate].cfg_options; | 55 | let cfg_options = &crate_graph[def_map.krate].cfg_options; |
56 | let proc_macros = &crate_graph[def_map.krate].proc_macro; | ||
57 | let proc_macros = proc_macros | ||
58 | .iter() | ||
59 | .enumerate() | ||
60 | .map(|(idx, it)| { | ||
61 | // FIXME: a hacky way to create a Name from string. | ||
62 | let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() }; | ||
63 | (name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx as u32))) | ||
64 | }) | ||
65 | .collect(); | ||
56 | 66 | ||
57 | let mut collector = DefCollector { | 67 | let mut collector = DefCollector { |
58 | db, | 68 | db, |
@@ -65,9 +75,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
65 | unexpanded_attribute_macros: Vec::new(), | 75 | unexpanded_attribute_macros: Vec::new(), |
66 | mod_dirs: FxHashMap::default(), | 76 | mod_dirs: FxHashMap::default(), |
67 | cfg_options, | 77 | cfg_options, |
68 | 78 | proc_macros, | |
69 | // FIXME: pass proc-macro from crate-graph | ||
70 | proc_macros: Default::default(), | ||
71 | }; | 79 | }; |
72 | collector.collect(); | 80 | collector.collect(); |
73 | collector.finish() | 81 | collector.finish() |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 1631e87b8..8f190e7f9 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -209,11 +209,8 @@ impl RawItemsCollector { | |||
209 | current_module: Option<Idx<ModuleData>>, | 209 | current_module: Option<Idx<ModuleData>>, |
210 | body: impl ast::ModuleItemOwner, | 210 | body: impl ast::ModuleItemOwner, |
211 | ) { | 211 | ) { |
212 | for item_or_macro in body.items_with_macros() { | 212 | for item in body.items() { |
213 | match item_or_macro { | 213 | self.add_item(current_module, item) |
214 | ast::ItemOrMacro::Macro(m) => self.add_macro(current_module, m), | ||
215 | ast::ItemOrMacro::Item(item) => self.add_item(current_module, item), | ||
216 | } | ||
217 | } | 214 | } |
218 | } | 215 | } |
219 | 216 | ||
@@ -265,6 +262,10 @@ impl RawItemsCollector { | |||
265 | ast::ModuleItem::StaticDef(it) => { | 262 | ast::ModuleItem::StaticDef(it) => { |
266 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) | 263 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) |
267 | } | 264 | } |
265 | ast::ModuleItem::MacroCall(it) => { | ||
266 | self.add_macro(current_module, it); | ||
267 | return; | ||
268 | } | ||
268 | }; | 269 | }; |
269 | if let Some(name) = name { | 270 | if let Some(name) = name { |
270 | let name = name.as_name(); | 271 | let name = name.as_name(); |
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 83f429c29..496fc6b08 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -4,8 +4,8 @@ use ra_db::SourceDatabaseExt; | |||
4 | 4 | ||
5 | use super::*; | 5 | use super::*; |
6 | 6 | ||
7 | fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { | 7 | fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) { |
8 | let (mut db, pos) = TestDB::with_position(initial); | 8 | let (mut db, pos) = TestDB::with_position(ra_fixture_initial); |
9 | let krate = db.test_crate(); | 9 | let krate = db.test_crate(); |
10 | { | 10 | { |
11 | let events = db.log_executed(|| { | 11 | let events = db.log_executed(|| { |
@@ -13,7 +13,7 @@ fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { | |||
13 | }); | 13 | }); |
14 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | 14 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) |
15 | } | 15 | } |
16 | db.set_file_text(pos.file_id, Arc::new(file_change.to_string())); | 16 | db.set_file_text(pos.file_id, Arc::new(ra_fixture_change.to_string())); |
17 | 17 | ||
18 | { | 18 | { |
19 | let events = db.log_executed(|| { | 19 | let events = db.log_executed(|| { |
@@ -26,7 +26,7 @@ fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { | |||
26 | #[test] | 26 | #[test] |
27 | fn typing_inside_a_function_should_not_invalidate_def_map() { | 27 | fn typing_inside_a_function_should_not_invalidate_def_map() { |
28 | check_def_map_is_not_recomputed( | 28 | check_def_map_is_not_recomputed( |
29 | " | 29 | r" |
30 | //- /lib.rs | 30 | //- /lib.rs |
31 | mod foo;<|> | 31 | mod foo;<|> |
32 | 32 | ||
@@ -41,7 +41,7 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
41 | //- /foo/bar.rs | 41 | //- /foo/bar.rs |
42 | pub struct Baz; | 42 | pub struct Baz; |
43 | ", | 43 | ", |
44 | " | 44 | r" |
45 | mod foo; | 45 | mod foo; |
46 | 46 | ||
47 | use crate::foo::bar::Baz; | 47 | use crate::foo::bar::Baz; |
@@ -54,7 +54,7 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
54 | #[test] | 54 | #[test] |
55 | fn adding_inner_items_should_not_invalidate_def_map() { | 55 | fn adding_inner_items_should_not_invalidate_def_map() { |
56 | check_def_map_is_not_recomputed( | 56 | check_def_map_is_not_recomputed( |
57 | " | 57 | r" |
58 | //- /lib.rs | 58 | //- /lib.rs |
59 | struct S { a: i32} | 59 | struct S { a: i32} |
60 | enum E { A } | 60 | enum E { A } |
@@ -72,7 +72,7 @@ fn adding_inner_items_should_not_invalidate_def_map() { | |||
72 | //- /foo/bar.rs | 72 | //- /foo/bar.rs |
73 | pub struct Baz; | 73 | pub struct Baz; |
74 | ", | 74 | ", |
75 | " | 75 | r" |
76 | struct S { a: i32, b: () } | 76 | struct S { a: i32, b: () } |
77 | enum E { A, B } | 77 | enum E { A, B } |
78 | trait T { | 78 | trait T { |
@@ -92,7 +92,7 @@ fn adding_inner_items_should_not_invalidate_def_map() { | |||
92 | #[test] | 92 | #[test] |
93 | fn typing_inside_a_macro_should_not_invalidate_def_map() { | 93 | fn typing_inside_a_macro_should_not_invalidate_def_map() { |
94 | let (mut db, pos) = TestDB::with_position( | 94 | let (mut db, pos) = TestDB::with_position( |
95 | " | 95 | r" |
96 | //- /lib.rs | 96 | //- /lib.rs |
97 | macro_rules! m { | 97 | macro_rules! m { |
98 | ($ident:ident) => { | 98 | ($ident:ident) => { |
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs index a6644d55f..5643ecdce 100644 --- a/crates/ra_hir_expand/src/ast_id_map.rs +++ b/crates/ra_hir_expand/src/ast_id_map.rs | |||
@@ -68,8 +68,6 @@ impl AstIdMap { | |||
68 | bfs(node, |it| { | 68 | bfs(node, |it| { |
69 | if let Some(module_item) = ast::ModuleItem::cast(it.clone()) { | 69 | if let Some(module_item) = ast::ModuleItem::cast(it.clone()) { |
70 | res.alloc(module_item.syntax()); | 70 | res.alloc(module_item.syntax()); |
71 | } else if let Some(macro_call) = ast::MacroCall::cast(it) { | ||
72 | res.alloc(macro_call.syntax()); | ||
73 | } | 71 | } |
74 | }); | 72 | }); |
75 | res | 73 | res |
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs index a8dee2052..4d270e0de 100644 --- a/crates/ra_hir_expand/src/proc_macro.rs +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -1,33 +1,32 @@ | |||
1 | //! Proc Macro Expander stub | 1 | //! Proc Macro Expander stub |
2 | 2 | ||
3 | use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc}; | 3 | use crate::{db::AstDatabase, LazyMacroId}; |
4 | use ra_db::CrateId; | 4 | use ra_db::{CrateId, ProcMacroId}; |
5 | 5 | ||
6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] | 6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
7 | pub struct ProcMacroExpander { | 7 | pub struct ProcMacroExpander { |
8 | krate: CrateId, | 8 | krate: CrateId, |
9 | proc_macro_id: ProcMacroId, | ||
9 | } | 10 | } |
10 | 11 | ||
11 | impl ProcMacroExpander { | 12 | impl ProcMacroExpander { |
12 | pub fn new(krate: CrateId) -> ProcMacroExpander { | 13 | pub fn new(krate: CrateId, proc_macro_id: ProcMacroId) -> ProcMacroExpander { |
13 | ProcMacroExpander { krate } | 14 | ProcMacroExpander { krate, proc_macro_id } |
14 | } | 15 | } |
15 | 16 | ||
16 | pub fn expand( | 17 | pub fn expand( |
17 | &self, | 18 | &self, |
18 | db: &dyn AstDatabase, | 19 | db: &dyn AstDatabase, |
19 | id: LazyMacroId, | 20 | _id: LazyMacroId, |
20 | _tt: &tt::Subtree, | 21 | tt: &tt::Subtree, |
21 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 22 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
22 | let loc: MacroCallLoc = db.lookup_intern_macro(id); | 23 | let krate_graph = db.crate_graph(); |
23 | let name = match loc.kind { | 24 | let proc_macro = krate_graph[self.krate] |
24 | MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError), | 25 | .proc_macro |
25 | MacroCallKind::Attr(_, name) => name, | 26 | .get(self.proc_macro_id.0 as usize) |
26 | }; | 27 | .clone() |
28 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; | ||
27 | 29 | ||
28 | log::debug!("Proc-macro-expanding name = {}", name); | 30 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) |
29 | |||
30 | // Return nothing for now | ||
31 | return Ok(tt::Subtree::default()); | ||
32 | } | 31 | } |
33 | } | 32 | } |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 11fc2ac3d..1462b053f 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -22,6 +22,7 @@ use hir_expand::name::Name; | |||
22 | #[salsa::requires(salsa::Database)] | 22 | #[salsa::requires(salsa::Database)] |
23 | pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | 23 | pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { |
24 | #[salsa::invoke(infer_wait)] | 24 | #[salsa::invoke(infer_wait)] |
25 | #[salsa::transparent] | ||
25 | fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; | 26 | fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; |
26 | 27 | ||
27 | #[salsa::invoke(crate::infer::infer_query)] | 28 | #[salsa::invoke(crate::infer::infer_query)] |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 5ab06c6cf..e43414985 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -213,6 +213,7 @@ impl Analysis { | |||
213 | cfg_options, | 213 | cfg_options, |
214 | Env::default(), | 214 | Env::default(), |
215 | Default::default(), | 215 | Default::default(), |
216 | Default::default(), | ||
216 | ); | 217 | ); |
217 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); | 218 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); |
218 | change.set_crate_graph(crate_graph); | 219 | change.set_crate_graph(crate_graph); |
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index 2cf77a31f..2c13f206a 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs | |||
@@ -103,6 +103,7 @@ impl MockAnalysis { | |||
103 | cfg_options, | 103 | cfg_options, |
104 | Env::default(), | 104 | Env::default(), |
105 | Default::default(), | 105 | Default::default(), |
106 | Default::default(), | ||
106 | )); | 107 | )); |
107 | } else if path.ends_with("/lib.rs") { | 108 | } else if path.ends_with("/lib.rs") { |
108 | let crate_name = path.parent().unwrap().file_name().unwrap(); | 109 | let crate_name = path.parent().unwrap().file_name().unwrap(); |
@@ -113,6 +114,7 @@ impl MockAnalysis { | |||
113 | cfg_options, | 114 | cfg_options, |
114 | Env::default(), | 115 | Env::default(), |
115 | Default::default(), | 116 | Default::default(), |
117 | Default::default(), | ||
116 | ); | 118 | ); |
117 | if let Some(root_crate) = root_crate { | 119 | if let Some(root_crate) = root_crate { |
118 | crate_graph | 120 | crate_graph |
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index 76d130b9b..958b92bed 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs | |||
@@ -137,6 +137,7 @@ mod tests { | |||
137 | CfgOptions::default(), | 137 | CfgOptions::default(), |
138 | Env::default(), | 138 | Env::default(), |
139 | Default::default(), | 139 | Default::default(), |
140 | Default::default(), | ||
140 | ); | 141 | ); |
141 | let mut change = AnalysisChange::new(); | 142 | let mut change = AnalysisChange::new(); |
142 | change.set_crate_graph(crate_graph); | 143 | change.set_crate_graph(crate_graph); |
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 628cf6416..8446ef88e 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -311,6 +311,7 @@ impl RootDatabase { | |||
311 | hir::db::MacroDefQuery | 311 | hir::db::MacroDefQuery |
312 | hir::db::ParseMacroQuery | 312 | hir::db::ParseMacroQuery |
313 | hir::db::MacroExpandQuery | 313 | hir::db::MacroExpandQuery |
314 | hir::db::InternEagerExpansionQuery | ||
314 | 315 | ||
315 | // DefDatabase | 316 | // DefDatabase |
316 | hir::db::RawItemsQuery | 317 | hir::db::RawItemsQuery |
@@ -359,14 +360,21 @@ impl RootDatabase { | |||
359 | hir::db::ImplsInCrateQuery | 360 | hir::db::ImplsInCrateQuery |
360 | hir::db::ImplsForTraitQuery | 361 | hir::db::ImplsForTraitQuery |
361 | hir::db::InternTypeCtorQuery | 362 | hir::db::InternTypeCtorQuery |
363 | hir::db::InternTypeParamIdQuery | ||
362 | hir::db::InternChalkImplQuery | 364 | hir::db::InternChalkImplQuery |
363 | hir::db::InternAssocTyValueQuery | 365 | hir::db::InternAssocTyValueQuery |
364 | hir::db::AssociatedTyDataQuery | 366 | hir::db::AssociatedTyDataQuery |
365 | hir::db::AssociatedTyValueQuery | ||
366 | hir::db::TraitSolveQuery | ||
367 | hir::db::TraitDatumQuery | 367 | hir::db::TraitDatumQuery |
368 | hir::db::StructDatumQuery | 368 | hir::db::StructDatumQuery |
369 | hir::db::ImplDatumQuery | 369 | hir::db::ImplDatumQuery |
370 | hir::db::AssociatedTyValueQuery | ||
371 | hir::db::TraitSolveQuery | ||
372 | |||
373 | // SymbolsDatabase | ||
374 | crate::symbol_index::FileSymbolsQuery | ||
375 | |||
376 | // LineIndexDatabase | ||
377 | crate::LineIndexQuery | ||
370 | ]; | 378 | ]; |
371 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 379 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
372 | acc | 380 | acc |
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 6a9037bfc..535b7daa0 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -28,6 +28,13 @@ pub enum ExpandError { | |||
28 | BindingError(String), | 28 | BindingError(String), |
29 | ConversionError, | 29 | ConversionError, |
30 | InvalidRepeat, | 30 | InvalidRepeat, |
31 | ProcMacroError(tt::ExpansionError), | ||
32 | } | ||
33 | |||
34 | impl From<tt::ExpansionError> for ExpandError { | ||
35 | fn from(it: tt::ExpansionError) -> Self { | ||
36 | ExpandError::ProcMacroError(it) | ||
37 | } | ||
31 | } | 38 | } |
32 | 39 | ||
33 | pub use crate::syntax_bridge::{ | 40 | pub use crate::syntax_bridge::{ |
diff --git a/crates/ra_proc_macro/Cargo.toml b/crates/ra_proc_macro/Cargo.toml new file mode 100644 index 000000000..bc2c37296 --- /dev/null +++ b/crates/ra_proc_macro/Cargo.toml | |||
@@ -0,0 +1,12 @@ | |||
1 | [package] | ||
2 | edition = "2018" | ||
3 | name = "ra_proc_macro" | ||
4 | version = "0.1.0" | ||
5 | authors = ["rust-analyzer developers"] | ||
6 | publish = false | ||
7 | |||
8 | [lib] | ||
9 | doctest = false | ||
10 | |||
11 | [dependencies] | ||
12 | ra_tt = { path = "../ra_tt" } | ||
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs new file mode 100644 index 000000000..5e21dd487 --- /dev/null +++ b/crates/ra_proc_macro/src/lib.rs | |||
@@ -0,0 +1,59 @@ | |||
1 | //! Client-side Proc-Macro crate | ||
2 | //! | ||
3 | //! We separate proc-macro expanding logic to an extern program to allow | ||
4 | //! different implementations (e.g. wasm or dylib loading). And this crate | ||
5 | //! is used to provide basic infrastructure for communication between two | ||
6 | //! processes: Client (RA itself), Server (the external program) | ||
7 | |||
8 | use ra_tt::{SmolStr, Subtree}; | ||
9 | use std::{ | ||
10 | path::{Path, PathBuf}, | ||
11 | sync::Arc, | ||
12 | }; | ||
13 | |||
14 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
15 | pub struct ProcMacroProcessExpander { | ||
16 | process: Arc<ProcMacroProcessSrv>, | ||
17 | name: SmolStr, | ||
18 | } | ||
19 | |||
20 | impl ra_tt::TokenExpander for ProcMacroProcessExpander { | ||
21 | fn expand( | ||
22 | &self, | ||
23 | _subtree: &Subtree, | ||
24 | _attr: Option<&Subtree>, | ||
25 | ) -> Result<Subtree, ra_tt::ExpansionError> { | ||
26 | // FIXME: do nothing for now | ||
27 | Ok(Subtree::default()) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
32 | pub struct ProcMacroProcessSrv { | ||
33 | path: PathBuf, | ||
34 | } | ||
35 | |||
36 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
37 | pub enum ProcMacroClient { | ||
38 | Process { process: Arc<ProcMacroProcessSrv> }, | ||
39 | Dummy, | ||
40 | } | ||
41 | |||
42 | impl ProcMacroClient { | ||
43 | pub fn extern_process(process_path: &Path) -> ProcMacroClient { | ||
44 | let process = ProcMacroProcessSrv { path: process_path.into() }; | ||
45 | ProcMacroClient::Process { process: Arc::new(process) } | ||
46 | } | ||
47 | |||
48 | pub fn dummy() -> ProcMacroClient { | ||
49 | ProcMacroClient::Dummy | ||
50 | } | ||
51 | |||
52 | pub fn by_dylib_path( | ||
53 | &self, | ||
54 | _dylib_path: &Path, | ||
55 | ) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> { | ||
56 | // FIXME: return empty for now | ||
57 | vec![] | ||
58 | } | ||
59 | } | ||
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index 22300548a..cdcdd63c9 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml | |||
@@ -17,6 +17,7 @@ ra_arena = { path = "../ra_arena" } | |||
17 | ra_db = { path = "../ra_db" } | 17 | ra_db = { path = "../ra_db" } |
18 | ra_cfg = { path = "../ra_cfg" } | 18 | ra_cfg = { path = "../ra_cfg" } |
19 | ra_cargo_watch = { path = "../ra_cargo_watch" } | 19 | ra_cargo_watch = { path = "../ra_cargo_watch" } |
20 | ra_proc_macro = { path = "../ra_proc_macro" } | ||
20 | 21 | ||
21 | serde = { version = "1.0.104", features = ["derive"] } | 22 | serde = { version = "1.0.104", features = ["derive"] } |
22 | serde_json = "1.0.48" | 23 | serde_json = "1.0.48" |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index c7f9bd873..291594e2a 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -83,6 +83,7 @@ pub struct PackageData { | |||
83 | pub edition: Edition, | 83 | pub edition: Edition, |
84 | pub features: Vec<String>, | 84 | pub features: Vec<String>, |
85 | pub out_dir: Option<PathBuf>, | 85 | pub out_dir: Option<PathBuf>, |
86 | pub proc_macro_dylib_path: Option<PathBuf>, | ||
86 | } | 87 | } |
87 | 88 | ||
88 | #[derive(Debug, Clone)] | 89 | #[derive(Debug, Clone)] |
@@ -158,8 +159,11 @@ impl CargoWorkspace { | |||
158 | })?; | 159 | })?; |
159 | 160 | ||
160 | let mut out_dir_by_id = FxHashMap::default(); | 161 | let mut out_dir_by_id = FxHashMap::default(); |
162 | let mut proc_macro_dylib_paths = FxHashMap::default(); | ||
161 | if cargo_features.load_out_dirs_from_check { | 163 | if cargo_features.load_out_dirs_from_check { |
162 | out_dir_by_id = load_out_dirs(cargo_toml, cargo_features); | 164 | let resources = load_extern_resources(cargo_toml, cargo_features); |
165 | out_dir_by_id = resources.out_dirs; | ||
166 | proc_macro_dylib_paths = resources.proc_dylib_paths; | ||
163 | } | 167 | } |
164 | 168 | ||
165 | let mut pkg_by_id = FxHashMap::default(); | 169 | let mut pkg_by_id = FxHashMap::default(); |
@@ -183,6 +187,7 @@ impl CargoWorkspace { | |||
183 | dependencies: Vec::new(), | 187 | dependencies: Vec::new(), |
184 | features: Vec::new(), | 188 | features: Vec::new(), |
185 | out_dir: out_dir_by_id.get(&id).cloned(), | 189 | out_dir: out_dir_by_id.get(&id).cloned(), |
190 | proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(), | ||
186 | }); | 191 | }); |
187 | let pkg_data = &mut packages[pkg]; | 192 | let pkg_data = &mut packages[pkg]; |
188 | pkg_by_id.insert(id, pkg); | 193 | pkg_by_id.insert(id, pkg); |
@@ -246,10 +251,13 @@ impl CargoWorkspace { | |||
246 | } | 251 | } |
247 | } | 252 | } |
248 | 253 | ||
249 | pub fn load_out_dirs( | 254 | #[derive(Debug, Clone, Default)] |
250 | cargo_toml: &Path, | 255 | pub struct ExternResources { |
251 | cargo_features: &CargoFeatures, | 256 | out_dirs: FxHashMap<PackageId, PathBuf>, |
252 | ) -> FxHashMap<PackageId, PathBuf> { | 257 | proc_dylib_paths: FxHashMap<PackageId, PathBuf>, |
258 | } | ||
259 | |||
260 | pub fn load_extern_resources(cargo_toml: &Path, cargo_features: &CargoFeatures) -> ExternResources { | ||
253 | let mut args: Vec<String> = vec![ | 261 | let mut args: Vec<String> = vec![ |
254 | "check".to_string(), | 262 | "check".to_string(), |
255 | "--message-format=json".to_string(), | 263 | "--message-format=json".to_string(), |
@@ -267,14 +275,21 @@ pub fn load_out_dirs( | |||
267 | args.extend(cargo_features.features.iter().cloned()); | 275 | args.extend(cargo_features.features.iter().cloned()); |
268 | } | 276 | } |
269 | 277 | ||
270 | let mut acc = FxHashMap::default(); | 278 | let mut acc = ExternResources::default(); |
271 | let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { | 279 | let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { |
272 | match message { | 280 | match message { |
273 | Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { | 281 | Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { |
274 | acc.insert(package_id, out_dir); | 282 | acc.out_dirs.insert(package_id, out_dir); |
275 | } | 283 | } |
276 | 284 | ||
277 | Message::CompilerArtifact(_) => (), | 285 | Message::CompilerArtifact(message) => { |
286 | if message.target.kind.contains(&"proc-macro".to_string()) { | ||
287 | let package_id = message.package_id; | ||
288 | if let Some(filename) = message.filenames.get(0) { | ||
289 | acc.proc_dylib_paths.insert(package_id, filename.clone()); | ||
290 | } | ||
291 | } | ||
292 | } | ||
278 | Message::CompilerMessage(_) => (), | 293 | Message::CompilerMessage(_) => (), |
279 | Message::Unknown => (), | 294 | Message::Unknown => (), |
280 | } | 295 | } |
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs index 336446e58..b030c8a6a 100644 --- a/crates/ra_project_model/src/json_project.rs +++ b/crates/ra_project_model/src/json_project.rs | |||
@@ -23,6 +23,7 @@ pub struct Crate { | |||
23 | pub(crate) atom_cfgs: FxHashSet<String>, | 23 | pub(crate) atom_cfgs: FxHashSet<String>, |
24 | pub(crate) key_value_cfgs: FxHashMap<String, String>, | 24 | pub(crate) key_value_cfgs: FxHashMap<String, String>, |
25 | pub(crate) out_dir: Option<PathBuf>, | 25 | pub(crate) out_dir: Option<PathBuf>, |
26 | pub(crate) proc_macro_dylib_path: Option<PathBuf>, | ||
26 | } | 27 | } |
27 | 28 | ||
28 | #[derive(Clone, Copy, Debug, Deserialize)] | 29 | #[derive(Clone, Copy, Debug, Deserialize)] |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index a3ef9acdc..444d3bb3f 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -23,6 +23,7 @@ pub use crate::{ | |||
23 | json_project::JsonProject, | 23 | json_project::JsonProject, |
24 | sysroot::Sysroot, | 24 | sysroot::Sysroot, |
25 | }; | 25 | }; |
26 | pub use ra_proc_macro::ProcMacroClient; | ||
26 | 27 | ||
27 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
28 | pub struct CargoTomlNotFoundError { | 29 | pub struct CargoTomlNotFoundError { |
@@ -173,6 +174,29 @@ impl ProjectWorkspace { | |||
173 | } | 174 | } |
174 | } | 175 | } |
175 | 176 | ||
177 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { | ||
178 | match self { | ||
179 | ProjectWorkspace::Json { project } => { | ||
180 | let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len()); | ||
181 | for krate in &project.crates { | ||
182 | if let Some(out_dir) = &krate.proc_macro_dylib_path { | ||
183 | proc_macro_dylib_paths.push(out_dir.to_path_buf()); | ||
184 | } | ||
185 | } | ||
186 | proc_macro_dylib_paths | ||
187 | } | ||
188 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | ||
189 | let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len()); | ||
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 | } | ||
198 | } | ||
199 | |||
176 | pub fn n_packages(&self) -> usize { | 200 | pub fn n_packages(&self) -> usize { |
177 | match self { | 201 | match self { |
178 | ProjectWorkspace::Json { project } => project.crates.len(), | 202 | ProjectWorkspace::Json { project } => project.crates.len(), |
@@ -186,6 +210,7 @@ impl ProjectWorkspace { | |||
186 | &self, | 210 | &self, |
187 | default_cfg_options: &CfgOptions, | 211 | default_cfg_options: &CfgOptions, |
188 | extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, | 212 | extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, |
213 | proc_macro_client: &ProcMacroClient, | ||
189 | load: &mut dyn FnMut(&Path) -> Option<FileId>, | 214 | load: &mut dyn FnMut(&Path) -> Option<FileId>, |
190 | ) -> CrateGraph { | 215 | ) -> CrateGraph { |
191 | let mut crate_graph = CrateGraph::default(); | 216 | let mut crate_graph = CrateGraph::default(); |
@@ -219,7 +244,10 @@ impl ProjectWorkspace { | |||
219 | extern_source.set_extern_path(&out_dir, extern_source_id); | 244 | extern_source.set_extern_path(&out_dir, extern_source_id); |
220 | } | 245 | } |
221 | } | 246 | } |
222 | 247 | let proc_macro = krate | |
248 | .proc_macro_dylib_path | ||
249 | .clone() | ||
250 | .map(|it| proc_macro_client.by_dylib_path(&it)); | ||
223 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 251 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
224 | crates.insert( | 252 | crates.insert( |
225 | crate_id, | 253 | crate_id, |
@@ -231,6 +259,7 @@ impl ProjectWorkspace { | |||
231 | cfg_options, | 259 | cfg_options, |
232 | env, | 260 | env, |
233 | extern_source, | 261 | extern_source, |
262 | proc_macro.unwrap_or_default(), | ||
234 | ), | 263 | ), |
235 | ); | 264 | ); |
236 | } | 265 | } |
@@ -270,6 +299,8 @@ impl ProjectWorkspace { | |||
270 | 299 | ||
271 | let env = Env::default(); | 300 | let env = Env::default(); |
272 | let extern_source = ExternSource::default(); | 301 | let extern_source = ExternSource::default(); |
302 | let proc_macro = vec![]; | ||
303 | |||
273 | let crate_id = crate_graph.add_crate_root( | 304 | let crate_id = crate_graph.add_crate_root( |
274 | file_id, | 305 | file_id, |
275 | Edition::Edition2018, | 306 | Edition::Edition2018, |
@@ -280,6 +311,7 @@ impl ProjectWorkspace { | |||
280 | cfg_options, | 311 | cfg_options, |
281 | env, | 312 | env, |
282 | extern_source, | 313 | extern_source, |
314 | proc_macro, | ||
283 | ); | 315 | ); |
284 | sysroot_crates.insert(krate, crate_id); | 316 | sysroot_crates.insert(krate, crate_id); |
285 | } | 317 | } |
@@ -327,6 +359,12 @@ impl ProjectWorkspace { | |||
327 | extern_source.set_extern_path(&out_dir, extern_source_id); | 359 | extern_source.set_extern_path(&out_dir, extern_source_id); |
328 | } | 360 | } |
329 | } | 361 | } |
362 | let proc_macro = cargo[pkg] | ||
363 | .proc_macro_dylib_path | ||
364 | .as_ref() | ||
365 | .map(|it| proc_macro_client.by_dylib_path(&it)) | ||
366 | .unwrap_or_default(); | ||
367 | |||
330 | let crate_id = crate_graph.add_crate_root( | 368 | let crate_id = crate_graph.add_crate_root( |
331 | file_id, | 369 | file_id, |
332 | edition, | 370 | edition, |
@@ -334,6 +372,7 @@ impl ProjectWorkspace { | |||
334 | cfg_options, | 372 | cfg_options, |
335 | env, | 373 | env, |
336 | extern_source, | 374 | extern_source, |
375 | proc_macro.clone(), | ||
337 | ); | 376 | ); |
338 | if cargo[tgt].kind == TargetKind::Lib { | 377 | if cargo[tgt].kind == TargetKind::Lib { |
339 | lib_tgt = Some((crate_id, cargo[tgt].name.clone())); | 378 | lib_tgt = Some((crate_id, cargo[tgt].name.clone())); |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 002f453cd..7204ca5b1 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -4135,6 +4135,7 @@ pub enum ModuleItem { | |||
4135 | ConstDef(ConstDef), | 4135 | ConstDef(ConstDef), |
4136 | StaticDef(StaticDef), | 4136 | StaticDef(StaticDef), |
4137 | Module(Module), | 4137 | Module(Module), |
4138 | MacroCall(MacroCall), | ||
4138 | } | 4139 | } |
4139 | impl From<StructDef> for ModuleItem { | 4140 | impl From<StructDef> for ModuleItem { |
4140 | fn from(node: StructDef) -> ModuleItem { | 4141 | fn from(node: StructDef) -> ModuleItem { |
@@ -4196,6 +4197,11 @@ impl From<Module> for ModuleItem { | |||
4196 | ModuleItem::Module(node) | 4197 | ModuleItem::Module(node) |
4197 | } | 4198 | } |
4198 | } | 4199 | } |
4200 | impl From<MacroCall> for ModuleItem { | ||
4201 | fn from(node: MacroCall) -> ModuleItem { | ||
4202 | ModuleItem::MacroCall(node) | ||
4203 | } | ||
4204 | } | ||
4199 | impl std::fmt::Display for ModuleItem { | 4205 | impl std::fmt::Display for ModuleItem { |
4200 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 4206 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
4201 | std::fmt::Display::fmt(self.syntax(), f) | 4207 | std::fmt::Display::fmt(self.syntax(), f) |
@@ -4205,7 +4211,7 @@ impl AstNode for ModuleItem { | |||
4205 | fn can_cast(kind: SyntaxKind) -> bool { | 4211 | fn can_cast(kind: SyntaxKind) -> bool { |
4206 | match kind { | 4212 | match kind { |
4207 | STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_DEF | 4213 | STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_DEF |
4208 | | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true, | 4214 | | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE | MACRO_CALL => true, |
4209 | _ => false, | 4215 | _ => false, |
4210 | } | 4216 | } |
4211 | } | 4217 | } |
@@ -4223,6 +4229,7 @@ impl AstNode for ModuleItem { | |||
4223 | CONST_DEF => ModuleItem::ConstDef(ConstDef { syntax }), | 4229 | CONST_DEF => ModuleItem::ConstDef(ConstDef { syntax }), |
4224 | STATIC_DEF => ModuleItem::StaticDef(StaticDef { syntax }), | 4230 | STATIC_DEF => ModuleItem::StaticDef(StaticDef { syntax }), |
4225 | MODULE => ModuleItem::Module(Module { syntax }), | 4231 | MODULE => ModuleItem::Module(Module { syntax }), |
4232 | MACRO_CALL => ModuleItem::MacroCall(MacroCall { syntax }), | ||
4226 | _ => return None, | 4233 | _ => return None, |
4227 | }; | 4234 | }; |
4228 | Some(res) | 4235 | Some(res) |
@@ -4241,6 +4248,7 @@ impl AstNode for ModuleItem { | |||
4241 | ModuleItem::ConstDef(it) => &it.syntax, | 4248 | ModuleItem::ConstDef(it) => &it.syntax, |
4242 | ModuleItem::StaticDef(it) => &it.syntax, | 4249 | ModuleItem::StaticDef(it) => &it.syntax, |
4243 | ModuleItem::Module(it) => &it.syntax, | 4250 | ModuleItem::Module(it) => &it.syntax, |
4251 | ModuleItem::MacroCall(it) => &it.syntax, | ||
4244 | } | 4252 | } |
4245 | } | 4253 | } |
4246 | } | 4254 | } |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 1145b69e8..e29600439 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -250,6 +250,10 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken { | |||
250 | .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) | 250 | .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) |
251 | } | 251 | } |
252 | 252 | ||
253 | pub fn unreachable_macro_call() -> ast::MacroCall { | ||
254 | ast_from_text(&format!("unreachable!()")) | ||
255 | } | ||
256 | |||
253 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 257 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
254 | let parse = SourceFile::parse(text); | 258 | let parse = SourceFile::parse(text); |
255 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 259 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index f8cf1e3eb..576378306 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs | |||
@@ -6,8 +6,7 @@ use itertools::Itertools; | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, | 8 | ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, |
9 | match_ast, | 9 | syntax_node::SyntaxElementChildren, |
10 | syntax_node::{SyntaxElementChildren, SyntaxNodeChildren}, | ||
11 | }; | 10 | }; |
12 | 11 | ||
13 | pub trait TypeAscriptionOwner: AstNode { | 12 | pub trait TypeAscriptionOwner: AstNode { |
@@ -46,38 +45,10 @@ pub trait FnDefOwner: AstNode { | |||
46 | } | 45 | } |
47 | } | 46 | } |
48 | 47 | ||
49 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
50 | pub enum ItemOrMacro { | ||
51 | Item(ast::ModuleItem), | ||
52 | Macro(ast::MacroCall), | ||
53 | } | ||
54 | |||
55 | pub trait ModuleItemOwner: AstNode { | 48 | pub trait ModuleItemOwner: AstNode { |
56 | fn items(&self) -> AstChildren<ast::ModuleItem> { | 49 | fn items(&self) -> AstChildren<ast::ModuleItem> { |
57 | children(self) | 50 | children(self) |
58 | } | 51 | } |
59 | fn items_with_macros(&self) -> ItemOrMacroIter { | ||
60 | ItemOrMacroIter(self.syntax().children()) | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #[derive(Debug)] | ||
65 | pub struct ItemOrMacroIter(SyntaxNodeChildren); | ||
66 | |||
67 | impl Iterator for ItemOrMacroIter { | ||
68 | type Item = ItemOrMacro; | ||
69 | fn next(&mut self) -> Option<ItemOrMacro> { | ||
70 | loop { | ||
71 | let n = self.0.next()?; | ||
72 | match_ast! { | ||
73 | match n { | ||
74 | ast::ModuleItem(it) => { return Some(ItemOrMacro::Item(it)) }, | ||
75 | ast::MacroCall(it) => { return Some(ItemOrMacro::Macro(it)) }, | ||
76 | _ => {}, | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | } | 52 | } |
82 | 53 | ||
83 | pub trait TypeParamsOwner: AstNode { | 54 | pub trait TypeParamsOwner: AstNode { |
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 1e2fb8b91..1015ce0a6 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs | |||
@@ -14,9 +14,12 @@ macro_rules! impl_froms { | |||
14 | } | 14 | } |
15 | } | 15 | } |
16 | 16 | ||
17 | use std::fmt; | 17 | use std::{ |
18 | fmt::{self, Debug}, | ||
19 | panic::RefUnwindSafe, | ||
20 | }; | ||
18 | 21 | ||
19 | use smol_str::SmolStr; | 22 | pub use smol_str::SmolStr; |
20 | 23 | ||
21 | /// Represents identity of the token. | 24 | /// Represents identity of the token. |
22 | /// | 25 | /// |
@@ -184,3 +187,11 @@ impl Subtree { | |||
184 | } | 187 | } |
185 | 188 | ||
186 | pub mod buffer; | 189 | pub mod buffer; |
190 | |||
191 | #[derive(Debug, PartialEq, Eq)] | ||
192 | pub enum ExpansionError {} | ||
193 | |||
194 | pub trait TokenExpander: Debug + Send + Sync + RefUnwindSafe { | ||
195 | fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>) | ||
196 | -> Result<Subtree, ExpansionError>; | ||
197 | } | ||
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 54e2fa1a7..832f04226 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -7,7 +7,9 @@ use anyhow::Result; | |||
7 | use crossbeam_channel::{unbounded, Receiver}; | 7 | use crossbeam_channel::{unbounded, Receiver}; |
8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; | 8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; |
9 | use ra_ide::{AnalysisChange, AnalysisHost}; | 9 | use ra_ide::{AnalysisChange, AnalysisHost}; |
10 | use ra_project_model::{get_rustc_cfg_options, CargoFeatures, PackageRoot, ProjectWorkspace}; | 10 | use ra_project_model::{ |
11 | get_rustc_cfg_options, CargoFeatures, PackageRoot, ProcMacroClient, ProjectWorkspace, | ||
12 | }; | ||
11 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; | 13 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; |
12 | use rustc_hash::{FxHashMap, FxHashSet}; | 14 | use rustc_hash::{FxHashMap, FxHashSet}; |
13 | 15 | ||
@@ -67,7 +69,9 @@ pub(crate) fn load_cargo( | |||
67 | (source_root_id, project_root) | 69 | (source_root_id, project_root) |
68 | }) | 70 | }) |
69 | .collect::<FxHashMap<_, _>>(); | 71 | .collect::<FxHashMap<_, _>>(); |
70 | let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs); | 72 | |
73 | let proc_macro_client = ProcMacroClient::dummy(); | ||
74 | let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client); | ||
71 | Ok((host, source_roots)) | 75 | Ok((host, source_roots)) |
72 | } | 76 | } |
73 | 77 | ||
@@ -77,6 +81,7 @@ pub(crate) fn load( | |||
77 | vfs: &mut Vfs, | 81 | vfs: &mut Vfs, |
78 | receiver: Receiver<VfsTask>, | 82 | receiver: Receiver<VfsTask>, |
79 | extern_dirs: FxHashSet<PathBuf>, | 83 | extern_dirs: FxHashSet<PathBuf>, |
84 | proc_macro_client: &ProcMacroClient, | ||
80 | ) -> AnalysisHost { | 85 | ) -> AnalysisHost { |
81 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); | 86 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); |
82 | let mut host = AnalysisHost::new(lru_cap); | 87 | let mut host = AnalysisHost::new(lru_cap); |
@@ -143,12 +148,16 @@ pub(crate) fn load( | |||
143 | opts | 148 | opts |
144 | }; | 149 | }; |
145 | 150 | ||
146 | let crate_graph = | 151 | let crate_graph = ws.to_crate_graph( |
147 | ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut |path: &Path| { | 152 | &default_cfg_options, |
153 | &extern_source_roots, | ||
154 | proc_macro_client, | ||
155 | &mut |path: &Path| { | ||
148 | let vfs_file = vfs.load(path); | 156 | let vfs_file = vfs.load(path); |
149 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); | 157 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); |
150 | vfs_file.map(vfs_file_to_id) | 158 | vfs_file.map(vfs_file_to_id) |
151 | }); | 159 | }, |
160 | ); | ||
152 | log::debug!("crate graph: {:?}", crate_graph); | 161 | log::debug!("crate graph: {:?}", crate_graph); |
153 | analysis_change.set_crate_graph(crate_graph); | 162 | analysis_change.set_crate_graph(crate_graph); |
154 | 163 | ||
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index c4244fee2..de85bb017 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -16,7 +16,7 @@ use ra_ide::{ | |||
16 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData, | 16 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData, |
17 | SourceRootId, | 17 | SourceRootId, |
18 | }; | 18 | }; |
19 | use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; | 19 | use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace}; |
20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; | 20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; |
21 | use relative_path::RelativePathBuf; | 21 | use relative_path::RelativePathBuf; |
22 | 22 | ||
@@ -150,9 +150,19 @@ impl WorldState { | |||
150 | vfs_file.map(|f| FileId(f.0)) | 150 | vfs_file.map(|f| FileId(f.0)) |
151 | }; | 151 | }; |
152 | 152 | ||
153 | let proc_macro_client = | ||
154 | ProcMacroClient::extern_process(std::path::Path::new("ra_proc_macro_srv")); | ||
155 | |||
153 | workspaces | 156 | workspaces |
154 | .iter() | 157 | .iter() |
155 | .map(|ws| ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut load)) | 158 | .map(|ws| { |
159 | ws.to_crate_graph( | ||
160 | &default_cfg_options, | ||
161 | &extern_source_roots, | ||
162 | &proc_macro_client, | ||
163 | &mut load, | ||
164 | ) | ||
165 | }) | ||
156 | .for_each(|graph| { | 166 | .for_each(|graph| { |
157 | crate_graph.extend(graph); | 167 | crate_graph.extend(graph); |
158 | }); | 168 | }); |