diff options
-rw-r--r-- | Cargo.lock | 13 | ||||
-rw-r--r-- | crates/ra_cargo_watch/src/conv.rs | 14 | ||||
-rw-r--r-- | crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap | 52 | ||||
-rw-r--r-- | crates/ra_cargo_watch/src/lib.rs | 67 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_db/src/symbol_index.rs | 7 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 27 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 13 |
12 files changed, 136 insertions, 123 deletions
diff --git a/Cargo.lock b/Cargo.lock index 3f4d9204c..f8d26192d 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -845,14 +845,9 @@ checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" | |||
845 | 845 | ||
846 | [[package]] | 846 | [[package]] |
847 | name = "proc-macro-hack" | 847 | name = "proc-macro-hack" |
848 | version = "0.5.12" | 848 | version = "0.5.14" |
849 | source = "registry+https://github.com/rust-lang/crates.io-index" | 849 | source = "registry+https://github.com/rust-lang/crates.io-index" |
850 | checksum = "f918f2b601f93baa836c1c2945faef682ba5b6d4828ecb45eeb7cc3c71b811b4" | 850 | checksum = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420" |
851 | dependencies = [ | ||
852 | "proc-macro2", | ||
853 | "quote", | ||
854 | "syn", | ||
855 | ] | ||
856 | 851 | ||
857 | [[package]] | 852 | [[package]] |
858 | name = "proc-macro2" | 853 | name = "proc-macro2" |
@@ -1480,9 +1475,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | |||
1480 | 1475 | ||
1481 | [[package]] | 1476 | [[package]] |
1482 | name = "syn" | 1477 | name = "syn" |
1483 | version = "1.0.16" | 1478 | version = "1.0.17" |
1484 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1485 | checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" | 1480 | checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" |
1486 | dependencies = [ | 1481 | dependencies = [ |
1487 | "proc-macro2", | 1482 | "proc-macro2", |
1488 | "quote", | 1483 | "quote", |
diff --git a/crates/ra_cargo_watch/src/conv.rs b/crates/ra_cargo_watch/src/conv.rs index c6f8ca329..817543deb 100644 --- a/crates/ra_cargo_watch/src/conv.rs +++ b/crates/ra_cargo_watch/src/conv.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | //! This module provides the functionality needed to convert diagnostics from | 1 | //! This module provides the functionality needed to convert diagnostics from |
2 | //! `cargo check` json format to the LSP diagnostic format. | 2 | //! `cargo check` json format to the LSP diagnostic format. |
3 | use cargo_metadata::diagnostic::{ | 3 | use cargo_metadata::diagnostic::{ |
4 | Diagnostic as RustDiagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion, | 4 | Applicability, Diagnostic as RustDiagnostic, DiagnosticLevel, DiagnosticSpan, |
5 | DiagnosticSpanMacroExpansion, | ||
5 | }; | 6 | }; |
6 | use lsp_types::{ | 7 | use lsp_types::{ |
7 | CodeAction, Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, | 8 | CodeAction, Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, |
@@ -136,10 +137,13 @@ fn map_rust_child_diagnostic( | |||
136 | 137 | ||
137 | let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new(); | 138 | let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new(); |
138 | for &span in &spans { | 139 | for &span in &spans { |
139 | if let Some(suggested_replacement) = &span.suggested_replacement { | 140 | match (&span.suggestion_applicability, &span.suggested_replacement) { |
140 | let location = map_span_to_location(span, workspace_root); | 141 | (Some(Applicability::MachineApplicable), Some(suggested_replacement)) => { |
141 | let edit = TextEdit::new(location.range, suggested_replacement.clone()); | 142 | let location = map_span_to_location(span, workspace_root); |
142 | edit_map.entry(location.uri).or_default().push(edit); | 143 | let edit = TextEdit::new(location.range, suggested_replacement.clone()); |
144 | edit_map.entry(location.uri).or_default().push(edit); | ||
145 | } | ||
146 | _ => {} | ||
143 | } | 147 | } |
144 | } | 148 | } |
145 | 149 | ||
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap index 9e8f4eff4..a59fa84fa 100644 --- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap +++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap | |||
@@ -58,44 +58,26 @@ expression: diag | |||
58 | }, | 58 | }, |
59 | message: "lint level defined here", | 59 | message: "lint level defined here", |
60 | }, | 60 | }, |
61 | DiagnosticRelatedInformation { | ||
62 | location: Location { | ||
63 | uri: "file:///test/compiler/mir/tagset.rs", | ||
64 | range: Range { | ||
65 | start: Position { | ||
66 | line: 41, | ||
67 | character: 23, | ||
68 | }, | ||
69 | end: Position { | ||
70 | line: 41, | ||
71 | character: 28, | ||
72 | }, | ||
73 | }, | ||
74 | }, | ||
75 | message: "consider passing by value instead", | ||
76 | }, | ||
61 | ], | 77 | ], |
62 | ), | 78 | ), |
63 | tags: None, | 79 | tags: None, |
64 | }, | 80 | }, |
65 | fixes: [ | 81 | fixes: [], |
66 | CodeAction { | ||
67 | title: "consider passing by value instead", | ||
68 | kind: Some( | ||
69 | "quickfix", | ||
70 | ), | ||
71 | diagnostics: None, | ||
72 | edit: Some( | ||
73 | WorkspaceEdit { | ||
74 | changes: Some( | ||
75 | { | ||
76 | "file:///test/compiler/mir/tagset.rs": [ | ||
77 | TextEdit { | ||
78 | range: Range { | ||
79 | start: Position { | ||
80 | line: 41, | ||
81 | character: 23, | ||
82 | }, | ||
83 | end: Position { | ||
84 | line: 41, | ||
85 | character: 28, | ||
86 | }, | ||
87 | }, | ||
88 | new_text: "self", | ||
89 | }, | ||
90 | ], | ||
91 | }, | ||
92 | ), | ||
93 | document_changes: None, | ||
94 | }, | ||
95 | ), | ||
96 | command: None, | ||
97 | is_preferred: None, | ||
98 | }, | ||
99 | ], | ||
100 | }, | 82 | }, |
101 | ] | 83 | ] |
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs index bffe5eb00..7c525c430 100644 --- a/crates/ra_cargo_watch/src/lib.rs +++ b/crates/ra_cargo_watch/src/lib.rs | |||
@@ -8,9 +8,10 @@ use lsp_types::{ | |||
8 | WorkDoneProgressEnd, WorkDoneProgressReport, | 8 | WorkDoneProgressEnd, WorkDoneProgressReport, |
9 | }; | 9 | }; |
10 | use std::{ | 10 | use std::{ |
11 | error, fmt, | ||
11 | io::{BufRead, BufReader}, | 12 | io::{BufRead, BufReader}, |
12 | path::{Path, PathBuf}, | 13 | path::{Path, PathBuf}, |
13 | process::{Child, Command, Stdio}, | 14 | process::{Command, Stdio}, |
14 | thread::JoinHandle, | 15 | thread::JoinHandle, |
15 | time::Instant, | 16 | time::Instant, |
16 | }; | 17 | }; |
@@ -70,10 +71,10 @@ impl std::ops::Drop for CheckWatcher { | |||
70 | fn drop(&mut self) { | 71 | fn drop(&mut self) { |
71 | if let Some(handle) = self.handle.take() { | 72 | if let Some(handle) = self.handle.take() { |
72 | // Take the sender out of the option | 73 | // Take the sender out of the option |
73 | let recv = self.cmd_send.take(); | 74 | let cmd_send = self.cmd_send.take(); |
74 | 75 | ||
75 | // Dropping the sender finishes the thread loop | 76 | // Dropping the sender finishes the thread loop |
76 | drop(recv); | 77 | drop(cmd_send); |
77 | 78 | ||
78 | // Join the thread, it should finish shortly. We don't really care | 79 | // Join the thread, it should finish shortly. We don't really care |
79 | // whether it panicked, so it is safe to ignore the result | 80 | // whether it panicked, so it is safe to ignore the result |
@@ -246,11 +247,21 @@ enum CheckEvent { | |||
246 | End, | 247 | End, |
247 | } | 248 | } |
248 | 249 | ||
250 | #[derive(Debug)] | ||
251 | pub struct CargoError(String); | ||
252 | |||
253 | impl fmt::Display for CargoError { | ||
254 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
255 | write!(f, "Cargo failed: {}", self.0) | ||
256 | } | ||
257 | } | ||
258 | impl error::Error for CargoError {} | ||
259 | |||
249 | pub fn run_cargo( | 260 | pub fn run_cargo( |
250 | args: &[String], | 261 | args: &[String], |
251 | current_dir: Option<&Path>, | 262 | current_dir: Option<&Path>, |
252 | on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, | 263 | on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, |
253 | ) -> Child { | 264 | ) -> Result<(), CargoError> { |
254 | let mut command = Command::new("cargo"); | 265 | let mut command = Command::new("cargo"); |
255 | if let Some(current_dir) = current_dir { | 266 | if let Some(current_dir) = current_dir { |
256 | command.current_dir(current_dir); | 267 | command.current_dir(current_dir); |
@@ -273,6 +284,8 @@ pub fn run_cargo( | |||
273 | // simply skip a line if it doesn't parse, which just ignores any | 284 | // simply skip a line if it doesn't parse, which just ignores any |
274 | // erroneus output. | 285 | // erroneus output. |
275 | let stdout = BufReader::new(child.stdout.take().unwrap()); | 286 | let stdout = BufReader::new(child.stdout.take().unwrap()); |
287 | let mut read_at_least_one_message = false; | ||
288 | |||
276 | for line in stdout.lines() { | 289 | for line in stdout.lines() { |
277 | let line = match line { | 290 | let line = match line { |
278 | Ok(line) => line, | 291 | Ok(line) => line, |
@@ -291,12 +304,31 @@ pub fn run_cargo( | |||
291 | } | 304 | } |
292 | }; | 305 | }; |
293 | 306 | ||
307 | read_at_least_one_message = true; | ||
308 | |||
294 | if !on_message(message) { | 309 | if !on_message(message) { |
295 | break; | 310 | break; |
296 | } | 311 | } |
297 | } | 312 | } |
298 | 313 | ||
299 | child | 314 | // It is okay to ignore the result, as it only errors if the process is already dead |
315 | let _ = child.kill(); | ||
316 | |||
317 | let err_msg = match child.wait() { | ||
318 | Ok(exit_code) if !exit_code.success() && !read_at_least_one_message => { | ||
319 | // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: | ||
320 | // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 | ||
321 | format!( | ||
322 | "the command produced no valid metadata (exit code: {:?}): cargo {}", | ||
323 | exit_code, | ||
324 | args.join(" ") | ||
325 | ) | ||
326 | } | ||
327 | Err(err) => format!("io error: {:?}", err), | ||
328 | Ok(_) => return Ok(()), | ||
329 | }; | ||
330 | |||
331 | Err(CargoError(err_msg)) | ||
300 | } | 332 | } |
301 | 333 | ||
302 | impl WatchThread { | 334 | impl WatchThread { |
@@ -325,7 +357,7 @@ impl WatchThread { | |||
325 | // which will break out of the loop, and continue the shutdown | 357 | // which will break out of the loop, and continue the shutdown |
326 | let _ = message_send.send(CheckEvent::Begin); | 358 | let _ = message_send.send(CheckEvent::Begin); |
327 | 359 | ||
328 | let mut child = run_cargo(&args, Some(&workspace_root), &mut |message| { | 360 | let res = run_cargo(&args, Some(&workspace_root), &mut |message| { |
329 | // Skip certain kinds of messages to only spend time on what's useful | 361 | // Skip certain kinds of messages to only spend time on what's useful |
330 | match &message { | 362 | match &message { |
331 | Message::CompilerArtifact(artifact) if artifact.fresh => return true, | 363 | Message::CompilerArtifact(artifact) if artifact.fresh => return true, |
@@ -334,26 +366,19 @@ impl WatchThread { | |||
334 | _ => {} | 366 | _ => {} |
335 | } | 367 | } |
336 | 368 | ||
337 | match message_send.send(CheckEvent::Msg(message)) { | 369 | // if the send channel was closed, we want to shutdown |
338 | Ok(()) => {} | 370 | message_send.send(CheckEvent::Msg(message)).is_ok() |
339 | Err(_err) => { | ||
340 | // The send channel was closed, so we want to shutdown | ||
341 | return false; | ||
342 | } | ||
343 | }; | ||
344 | |||
345 | true | ||
346 | }); | 371 | }); |
347 | 372 | ||
373 | if let Err(err) = res { | ||
374 | // FIXME: make the `message_send` to be `Sender<Result<CheckEvent, CargoError>>` | ||
375 | // to display user-caused misconfiguration errors instead of just logging them here | ||
376 | log::error!("Cargo watcher failed {:?}", err); | ||
377 | } | ||
378 | |||
348 | // We can ignore any error here, as we are already in the progress | 379 | // We can ignore any error here, as we are already in the progress |
349 | // of shutting down. | 380 | // of shutting down. |
350 | let _ = message_send.send(CheckEvent::End); | 381 | let _ = message_send.send(CheckEvent::End); |
351 | |||
352 | // It is okay to ignore the result, as it only errors if the process is already dead | ||
353 | let _ = child.kill(); | ||
354 | |||
355 | // Again, we don't care about the exit status so just ignore the result | ||
356 | let _ = child.wait(); | ||
357 | })) | 382 | })) |
358 | } else { | 383 | } else { |
359 | None | 384 | None |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 45e31095c..4b150ef06 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1042,30 +1042,18 @@ impl Type { | |||
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | pub fn is_bool(&self) -> bool { | 1044 | pub fn is_bool(&self) -> bool { |
1045 | match &self.ty.value { | 1045 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1046 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1047 | TypeCtor::Bool => true, | ||
1048 | _ => false, | ||
1049 | }, | ||
1050 | _ => false, | ||
1051 | } | ||
1052 | } | 1046 | } |
1053 | 1047 | ||
1054 | pub fn is_mutable_reference(&self) -> bool { | 1048 | pub fn is_mutable_reference(&self) -> bool { |
1055 | match &self.ty.value { | 1049 | matches!( |
1056 | Ty::Apply(a_ty) => match a_ty.ctor { | 1050 | self.ty.value, |
1057 | TypeCtor::Ref(Mutability::Mut) => true, | 1051 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. }) |
1058 | _ => false, | 1052 | ) |
1059 | }, | ||
1060 | _ => false, | ||
1061 | } | ||
1062 | } | 1053 | } |
1063 | 1054 | ||
1064 | pub fn is_unknown(&self) -> bool { | 1055 | pub fn is_unknown(&self) -> bool { |
1065 | match &self.ty.value { | 1056 | matches!(self.ty.value, Ty::Unknown) |
1066 | Ty::Unknown => true, | ||
1067 | _ => false, | ||
1068 | } | ||
1069 | } | 1057 | } |
1070 | 1058 | ||
1071 | /// Checks that particular type `ty` implements `std::future::Future`. | 1059 | /// Checks that particular type `ty` implements `std::future::Future`. |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9f59d590c..713d45f48 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -4,6 +4,18 @@ | |||
4 | //! The principal difference between HIR and syntax trees is that HIR is bound | 4 | //! The principal difference between HIR and syntax trees is that HIR is bound |
5 | //! to a particular crate instance. That is, it has cfg flags and features | 5 | //! to a particular crate instance. That is, it has cfg flags and features |
6 | //! applied. So, the relation between syntax and HIR is many-to-one. | 6 | //! applied. So, the relation between syntax and HIR is many-to-one. |
7 | //! | ||
8 | //! HIR is the public API of the all of the compiler logic above syntax trees. | ||
9 | //! It is written in "OO" style. Each type is self contained (as in, it knows it's | ||
10 | //! parents and full context). It should be "clean code". | ||
11 | //! | ||
12 | //! `ra_hir_*` crates are the implementation of the compiler logic. | ||
13 | //! They are written in "ECS" style, with relatively little abstractions. | ||
14 | //! Many types are not self-contained, and explicitly use local indexes, arenas, etc. | ||
15 | //! | ||
16 | //! `ra_hir` is what insulates the "we don't know how to actually write an incremental compiler" | ||
17 | //! from the ide with completions, hovers, etc. It is a (soft, internal) boundary: | ||
18 | //! https://www.tedinski.com/2018/02/06/system-boundaries.html. | ||
7 | 19 | ||
8 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
9 | 21 | ||
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e8c58ed32..3cf0c66ea 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -453,7 +453,7 @@ impl ExprCollector<'_> { | |||
453 | } | 453 | } |
454 | } | 454 | } |
455 | ast::Expr::MacroCall(e) => { | 455 | ast::Expr::MacroCall(e) => { |
456 | if let Some(name) = is_macro_rules(&e) { | 456 | if let Some(name) = e.is_macro_rules().map(|it| it.as_name()) { |
457 | let mac = MacroDefId { | 457 | let mac = MacroDefId { |
458 | krate: Some(self.expander.module.krate), | 458 | krate: Some(self.expander.module.krate), |
459 | ast_id: Some(self.expander.ast_id(&e)), | 459 | ast_id: Some(self.expander.ast_id(&e)), |
@@ -697,16 +697,6 @@ impl ExprCollector<'_> { | |||
697 | } | 697 | } |
698 | } | 698 | } |
699 | 699 | ||
700 | fn is_macro_rules(m: &ast::MacroCall) -> Option<Name> { | ||
701 | let name = m.path()?.segment()?.name_ref()?.as_name(); | ||
702 | |||
703 | if name == name![macro_rules] { | ||
704 | Some(m.name()?.as_name()) | ||
705 | } else { | ||
706 | None | ||
707 | } | ||
708 | } | ||
709 | |||
710 | impl From<ast::BinOp> for BinaryOp { | 700 | impl From<ast::BinOp> for BinaryOp { |
711 | fn from(ast_op: ast::BinOp) -> Self { | 701 | fn from(ast_op: ast::BinOp) -> Self { |
712 | match ast_op { | 702 | match ast_op { |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 246032c13..904080341 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -95,7 +95,7 @@ pub struct Path { | |||
95 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. | 95 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. |
96 | type_anchor: Option<Box<TypeRef>>, | 96 | type_anchor: Option<Box<TypeRef>>, |
97 | mod_path: ModPath, | 97 | mod_path: ModPath, |
98 | /// Invariant: the same len as self.path.segments | 98 | /// Invariant: the same len as `self.mod_path.segments` |
99 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 99 | generic_args: Vec<Option<Arc<GenericArgs>>>, |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 69c059ac8..533c6ccfb 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -95,14 +95,14 @@ impl Ty { | |||
95 | // Types like slice can have inherent impls in several crates, (core and alloc). | 95 | // Types like slice can have inherent impls in several crates, (core and alloc). |
96 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. | 96 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. |
97 | macro_rules! lang_item_crate { | 97 | macro_rules! lang_item_crate { |
98 | ($($name:expr),+ $(,)?) => {{ | 98 | ($($name:expr),+ $(,)?) => {{ |
99 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); | 99 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); |
100 | $( | 100 | $( |
101 | v.extend(db.lang_item(cur_crate, $name.into())); | 101 | v.extend(db.lang_item(cur_crate, $name.into())); |
102 | )+ | 102 | )+ |
103 | v | 103 | v |
104 | }}; | 104 | }}; |
105 | } | 105 | } |
106 | 106 | ||
107 | let lang_item_targets = match self { | 107 | let lang_item_targets = match self { |
108 | Ty::Apply(a_ty) => match a_ty.ctor { | 108 | Ty::Apply(a_ty) => match a_ty.ctor { |
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index 884359ee3..0f46f93c1 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs | |||
@@ -362,6 +362,13 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { | |||
362 | ast::TypeAliasDef(it) => { decl(it) }, | 362 | ast::TypeAliasDef(it) => { decl(it) }, |
363 | ast::ConstDef(it) => { decl(it) }, | 363 | ast::ConstDef(it) => { decl(it) }, |
364 | ast::StaticDef(it) => { decl(it) }, | 364 | ast::StaticDef(it) => { decl(it) }, |
365 | ast::MacroCall(it) => { | ||
366 | if it.is_macro_rules().is_some() { | ||
367 | decl(it) | ||
368 | } else { | ||
369 | None | ||
370 | } | ||
371 | }, | ||
365 | _ => None, | 372 | _ => None, |
366 | } | 373 | } |
367 | } | 374 | } |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index c2857dbfc..c7f9bd873 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use anyhow::{Context, Result}; | 8 | use anyhow::{Context, Result}; |
9 | use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId}; | 9 | use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; |
10 | use ra_arena::{Arena, Idx}; | 10 | use ra_arena::{Arena, Idx}; |
11 | use ra_cargo_watch::run_cargo; | 11 | use ra_cargo_watch::run_cargo; |
12 | use ra_db::Edition; | 12 | use ra_db::Edition; |
@@ -254,7 +254,7 @@ pub fn load_out_dirs( | |||
254 | "check".to_string(), | 254 | "check".to_string(), |
255 | "--message-format=json".to_string(), | 255 | "--message-format=json".to_string(), |
256 | "--manifest-path".to_string(), | 256 | "--manifest-path".to_string(), |
257 | format!("{}", cargo_toml.display()), | 257 | cargo_toml.display().to_string(), |
258 | ]; | 258 | ]; |
259 | 259 | ||
260 | if cargo_features.all_features { | 260 | if cargo_features.all_features { |
@@ -263,19 +263,15 @@ pub fn load_out_dirs( | |||
263 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | 263 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` |
264 | // https://github.com/oli-obk/cargo_metadata/issues/79 | 264 | // https://github.com/oli-obk/cargo_metadata/issues/79 |
265 | args.push("--no-default-features".to_string()); | 265 | args.push("--no-default-features".to_string()); |
266 | } else if !cargo_features.features.is_empty() { | 266 | } else { |
267 | for feature in &cargo_features.features { | 267 | args.extend(cargo_features.features.iter().cloned()); |
268 | args.push(feature.clone()); | ||
269 | } | ||
270 | } | 268 | } |
271 | 269 | ||
272 | let mut res = FxHashMap::default(); | 270 | let mut acc = FxHashMap::default(); |
273 | let mut child = run_cargo(&args, cargo_toml.parent(), &mut |message| { | 271 | let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { |
274 | match message { | 272 | match message { |
275 | Message::BuildScriptExecuted(message) => { | 273 | Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { |
276 | let package_id = message.package_id; | 274 | acc.insert(package_id, out_dir); |
277 | let out_dir = message.out_dir; | ||
278 | res.insert(package_id, out_dir); | ||
279 | } | 275 | } |
280 | 276 | ||
281 | Message::CompilerArtifact(_) => (), | 277 | Message::CompilerArtifact(_) => (), |
@@ -285,6 +281,9 @@ pub fn load_out_dirs( | |||
285 | true | 281 | true |
286 | }); | 282 | }); |
287 | 283 | ||
288 | let _ = child.wait(); | 284 | if let Err(err) = res { |
289 | res | 285 | log::error!("Failed to load outdirs: {:?}", err); |
286 | } | ||
287 | |||
288 | acc | ||
290 | } | 289 | } |
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index c3ae8f90e..392731dac 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -4,7 +4,7 @@ | |||
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode}, | 7 | ast::{self, child_opt, children, AstNode, AttrInput, NameOwner, SyntaxNode}, |
8 | SmolStr, SyntaxElement, | 8 | SmolStr, SyntaxElement, |
9 | SyntaxKind::*, | 9 | SyntaxKind::*, |
10 | SyntaxToken, T, | 10 | SyntaxToken, T, |
@@ -514,3 +514,14 @@ impl ast::Visibility { | |||
514 | self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) | 514 | self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) |
515 | } | 515 | } |
516 | } | 516 | } |
517 | |||
518 | impl ast::MacroCall { | ||
519 | pub fn is_macro_rules(&self) -> Option<ast::Name> { | ||
520 | let name_ref = self.path()?.segment()?.name_ref()?; | ||
521 | if name_ref.text() == "macro_rules" { | ||
522 | self.name() | ||
523 | } else { | ||
524 | None | ||
525 | } | ||
526 | } | ||
527 | } | ||