diff options
Diffstat (limited to 'crates')
24 files changed, 174 insertions, 215 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 92ec4f92e..1023d3040 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs | |||
@@ -5,8 +5,9 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | fmt, | 6 | fmt, |
7 | io::{self, BufReader}, | 7 | io::{self, BufReader}, |
8 | ops, | ||
8 | path::PathBuf, | 9 | path::PathBuf, |
9 | process::{Command, Stdio}, | 10 | process::{self, Command, Stdio}, |
10 | time::Duration, | 11 | time::Duration, |
11 | }; | 12 | }; |
12 | 13 | ||
@@ -49,8 +50,8 @@ impl fmt::Display for FlycheckConfig { | |||
49 | #[derive(Debug)] | 50 | #[derive(Debug)] |
50 | pub struct FlycheckHandle { | 51 | pub struct FlycheckHandle { |
51 | // XXX: drop order is significant | 52 | // XXX: drop order is significant |
52 | cmd_send: Sender<Restart>, | 53 | sender: Sender<Restart>, |
53 | handle: jod_thread::JoinHandle, | 54 | thread: jod_thread::JoinHandle, |
54 | } | 55 | } |
55 | 56 | ||
56 | impl FlycheckHandle { | 57 | impl FlycheckHandle { |
@@ -59,16 +60,15 @@ impl FlycheckHandle { | |||
59 | config: FlycheckConfig, | 60 | config: FlycheckConfig, |
60 | workspace_root: PathBuf, | 61 | workspace_root: PathBuf, |
61 | ) -> FlycheckHandle { | 62 | ) -> FlycheckHandle { |
62 | let (cmd_send, cmd_recv) = unbounded::<Restart>(); | 63 | let actor = FlycheckActor::new(sender, config, workspace_root); |
63 | let handle = jod_thread::spawn(move || { | 64 | let (sender, receiver) = unbounded::<Restart>(); |
64 | FlycheckActor::new(sender, config, workspace_root).run(cmd_recv); | 65 | let thread = jod_thread::spawn(move || actor.run(receiver)); |
65 | }); | 66 | FlycheckHandle { sender, thread } |
66 | FlycheckHandle { cmd_send, handle } | ||
67 | } | 67 | } |
68 | 68 | ||
69 | /// Schedule a re-start of the cargo check worker. | 69 | /// Schedule a re-start of the cargo check worker. |
70 | pub fn update(&self) { | 70 | pub fn update(&self) { |
71 | self.cmd_send.send(Restart).unwrap(); | 71 | self.sender.send(Restart).unwrap(); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
@@ -85,7 +85,7 @@ pub enum Message { | |||
85 | pub enum Progress { | 85 | pub enum Progress { |
86 | DidStart, | 86 | DidStart, |
87 | DidCheckCrate(String), | 87 | DidCheckCrate(String), |
88 | DidFinish, | 88 | DidFinish(io::Result<()>), |
89 | DidCancel, | 89 | DidCancel, |
90 | } | 90 | } |
91 | 91 | ||
@@ -100,8 +100,7 @@ struct FlycheckActor { | |||
100 | /// doesn't provide a way to read sub-process output without blocking, so we | 100 | /// doesn't provide a way to read sub-process output without blocking, so we |
101 | /// have to wrap sub-processes output handling in a thread and pass messages | 101 | /// have to wrap sub-processes output handling in a thread and pass messages |
102 | /// back over a channel. | 102 | /// back over a channel. |
103 | // XXX: drop order is significant | 103 | cargo_handle: Option<CargoHandle>, |
104 | check_process: Option<(Receiver<cargo_metadata::Message>, jod_thread::JoinHandle)>, | ||
105 | } | 104 | } |
106 | 105 | ||
107 | enum Event { | 106 | enum Event { |
@@ -115,29 +114,36 @@ impl FlycheckActor { | |||
115 | config: FlycheckConfig, | 114 | config: FlycheckConfig, |
116 | workspace_root: PathBuf, | 115 | workspace_root: PathBuf, |
117 | ) -> FlycheckActor { | 116 | ) -> FlycheckActor { |
118 | FlycheckActor { sender, config, workspace_root, check_process: None } | 117 | FlycheckActor { sender, config, workspace_root, cargo_handle: None } |
119 | } | 118 | } |
120 | fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> { | 119 | fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> { |
121 | let check_chan = self.check_process.as_ref().map(|(chan, _thread)| chan); | 120 | let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver); |
122 | select! { | 121 | select! { |
123 | recv(inbox) -> msg => msg.ok().map(Event::Restart), | 122 | recv(inbox) -> msg => msg.ok().map(Event::Restart), |
124 | recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())), | 123 | recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())), |
125 | } | 124 | } |
126 | } | 125 | } |
127 | fn run(&mut self, inbox: Receiver<Restart>) { | 126 | fn run(mut self, inbox: Receiver<Restart>) { |
128 | while let Some(event) = self.next_event(&inbox) { | 127 | while let Some(event) = self.next_event(&inbox) { |
129 | match event { | 128 | match event { |
130 | Event::Restart(Restart) => { | 129 | Event::Restart(Restart) => { |
131 | while let Ok(Restart) = inbox.recv_timeout(Duration::from_millis(50)) {} | 130 | while let Ok(Restart) = inbox.recv_timeout(Duration::from_millis(50)) {} |
131 | |||
132 | self.cancel_check_process(); | 132 | self.cancel_check_process(); |
133 | self.check_process = Some(self.start_check_process()); | 133 | |
134 | self.send(Message::Progress(Progress::DidStart)); | 134 | let mut command = self.check_command(); |
135 | command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); | ||
136 | if let Ok(child) = command.spawn().map(JodChild) { | ||
137 | self.cargo_handle = Some(CargoHandle::spawn(child)); | ||
138 | self.send(Message::Progress(Progress::DidStart)); | ||
139 | } | ||
135 | } | 140 | } |
136 | Event::CheckEvent(None) => { | 141 | Event::CheckEvent(None) => { |
137 | // Watcher finished, replace it with a never channel to | 142 | // Watcher finished, replace it with a never channel to |
138 | // avoid busy-waiting. | 143 | // avoid busy-waiting. |
139 | assert!(self.check_process.take().is_some()); | 144 | let cargo_handle = self.cargo_handle.take().unwrap(); |
140 | self.send(Message::Progress(Progress::DidFinish)); | 145 | let res = cargo_handle.join(); |
146 | self.send(Message::Progress(Progress::DidFinish(res))); | ||
141 | } | 147 | } |
142 | Event::CheckEvent(Some(message)) => match message { | 148 | Event::CheckEvent(Some(message)) => match message { |
143 | cargo_metadata::Message::CompilerArtifact(msg) => { | 149 | cargo_metadata::Message::CompilerArtifact(msg) => { |
@@ -162,11 +168,11 @@ impl FlycheckActor { | |||
162 | self.cancel_check_process(); | 168 | self.cancel_check_process(); |
163 | } | 169 | } |
164 | fn cancel_check_process(&mut self) { | 170 | fn cancel_check_process(&mut self) { |
165 | if self.check_process.take().is_some() { | 171 | if self.cargo_handle.take().is_some() { |
166 | self.send(Message::Progress(Progress::DidCancel)); | 172 | self.send(Message::Progress(Progress::DidCancel)); |
167 | } | 173 | } |
168 | } | 174 | } |
169 | fn start_check_process(&self) -> (Receiver<cargo_metadata::Message>, jod_thread::JoinHandle) { | 175 | fn check_command(&self) -> Command { |
170 | let mut cmd = match &self.config { | 176 | let mut cmd = match &self.config { |
171 | FlycheckConfig::CargoCommand { | 177 | FlycheckConfig::CargoCommand { |
172 | command, | 178 | command, |
@@ -198,33 +204,7 @@ impl FlycheckActor { | |||
198 | } | 204 | } |
199 | }; | 205 | }; |
200 | cmd.current_dir(&self.workspace_root); | 206 | cmd.current_dir(&self.workspace_root); |
201 | 207 | cmd | |
202 | let (message_send, message_recv) = unbounded(); | ||
203 | let thread = jod_thread::spawn(move || { | ||
204 | // If we trigger an error here, we will do so in the loop instead, | ||
205 | // which will break out of the loop, and continue the shutdown | ||
206 | let res = run_cargo(cmd, &mut |message| { | ||
207 | // Skip certain kinds of messages to only spend time on what's useful | ||
208 | match &message { | ||
209 | cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => { | ||
210 | return true | ||
211 | } | ||
212 | cargo_metadata::Message::BuildScriptExecuted(_) | ||
213 | | cargo_metadata::Message::Unknown => return true, | ||
214 | _ => {} | ||
215 | } | ||
216 | |||
217 | // if the send channel was closed, we want to shutdown | ||
218 | message_send.send(message).is_ok() | ||
219 | }); | ||
220 | |||
221 | if let Err(err) = res { | ||
222 | // FIXME: make the `message_send` to be `Sender<Result<CheckEvent, CargoError>>` | ||
223 | // to display user-caused misconfiguration errors instead of just logging them here | ||
224 | log::error!("Cargo watcher failed {:?}", err); | ||
225 | } | ||
226 | }); | ||
227 | (message_recv, thread) | ||
228 | } | 208 | } |
229 | 209 | ||
230 | fn send(&self, check_task: Message) { | 210 | fn send(&self, check_task: Message) { |
@@ -232,54 +212,104 @@ impl FlycheckActor { | |||
232 | } | 212 | } |
233 | } | 213 | } |
234 | 214 | ||
235 | fn run_cargo( | 215 | struct CargoHandle { |
236 | mut command: Command, | 216 | child: JodChild, |
237 | on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, | 217 | #[allow(unused)] |
238 | ) -> io::Result<()> { | 218 | thread: jod_thread::JoinHandle<io::Result<bool>>, |
239 | let mut child = | 219 | receiver: Receiver<cargo_metadata::Message>, |
240 | command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()).spawn()?; | 220 | } |
241 | 221 | ||
242 | // We manually read a line at a time, instead of using serde's | 222 | impl CargoHandle { |
243 | // stream deserializers, because the deserializer cannot recover | 223 | fn spawn(mut child: JodChild) -> CargoHandle { |
244 | // from an error, resulting in it getting stuck, because we try to | 224 | let child_stdout = child.stdout.take().unwrap(); |
245 | // be resillient against failures. | 225 | let (sender, receiver) = unbounded(); |
246 | // | 226 | let actor = CargoActor::new(child_stdout, sender); |
247 | // Because cargo only outputs one JSON object per line, we can | 227 | let thread = jod_thread::spawn(move || actor.run()); |
248 | // simply skip a line if it doesn't parse, which just ignores any | 228 | CargoHandle { child, thread, receiver } |
249 | // erroneus output. | 229 | } |
250 | let stdout = BufReader::new(child.stdout.take().unwrap()); | 230 | fn join(mut self) -> io::Result<()> { |
251 | let mut read_at_least_one_message = false; | 231 | // It is okay to ignore the result, as it only errors if the process is already dead |
252 | for message in cargo_metadata::Message::parse_stream(stdout) { | 232 | let _ = self.child.kill(); |
253 | let message = match message { | 233 | let exit_status = self.child.wait()?; |
254 | Ok(message) => message, | 234 | let read_at_least_one_message = self.thread.join()?; |
255 | Err(err) => { | 235 | if !exit_status.success() && !read_at_least_one_message { |
256 | log::error!("Invalid json from cargo check, ignoring ({})", err); | 236 | // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: |
257 | continue; | 237 | // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 |
258 | } | 238 | return Err(io::Error::new( |
259 | }; | 239 | io::ErrorKind::Other, |
240 | format!( | ||
241 | "Cargo watcher failed,the command produced no valid metadata (exit code: {:?})", | ||
242 | exit_status | ||
243 | ), | ||
244 | )); | ||
245 | } | ||
246 | Ok(()) | ||
247 | } | ||
248 | } | ||
249 | |||
250 | struct CargoActor { | ||
251 | child_stdout: process::ChildStdout, | ||
252 | sender: Sender<cargo_metadata::Message>, | ||
253 | } | ||
254 | |||
255 | impl CargoActor { | ||
256 | fn new( | ||
257 | child_stdout: process::ChildStdout, | ||
258 | sender: Sender<cargo_metadata::Message>, | ||
259 | ) -> CargoActor { | ||
260 | CargoActor { child_stdout, sender } | ||
261 | } | ||
262 | fn run(self) -> io::Result<bool> { | ||
263 | // We manually read a line at a time, instead of using serde's | ||
264 | // stream deserializers, because the deserializer cannot recover | ||
265 | // from an error, resulting in it getting stuck, because we try to | ||
266 | // be resilient against failures. | ||
267 | // | ||
268 | // Because cargo only outputs one JSON object per line, we can | ||
269 | // simply skip a line if it doesn't parse, which just ignores any | ||
270 | // erroneus output. | ||
271 | let stdout = BufReader::new(self.child_stdout); | ||
272 | let mut read_at_least_one_message = false; | ||
273 | for message in cargo_metadata::Message::parse_stream(stdout) { | ||
274 | let message = match message { | ||
275 | Ok(message) => message, | ||
276 | Err(err) => { | ||
277 | log::error!("Invalid json from cargo check, ignoring ({})", err); | ||
278 | continue; | ||
279 | } | ||
280 | }; | ||
260 | 281 | ||
261 | read_at_least_one_message = true; | 282 | read_at_least_one_message = true; |
262 | 283 | ||
263 | if !on_message(message) { | 284 | // Skip certain kinds of messages to only spend time on what's useful |
264 | break; | 285 | match &message { |
286 | cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), | ||
287 | cargo_metadata::Message::BuildScriptExecuted(_) | ||
288 | | cargo_metadata::Message::Unknown => (), | ||
289 | _ => self.sender.send(message).unwrap(), | ||
290 | } | ||
265 | } | 291 | } |
292 | Ok(read_at_least_one_message) | ||
266 | } | 293 | } |
294 | } | ||
267 | 295 | ||
268 | // It is okay to ignore the result, as it only errors if the process is already dead | 296 | struct JodChild(process::Child); |
269 | let _ = child.kill(); | ||
270 | 297 | ||
271 | let exit_status = child.wait()?; | 298 | impl ops::Deref for JodChild { |
272 | if !exit_status.success() && !read_at_least_one_message { | 299 | type Target = process::Child; |
273 | // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: | 300 | fn deref(&self) -> &process::Child { |
274 | // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 | 301 | &self.0 |
275 | return Err(io::Error::new( | ||
276 | io::ErrorKind::Other, | ||
277 | format!( | ||
278 | "the command produced no valid metadata (exit code: {:?}): {:?}", | ||
279 | exit_status, command | ||
280 | ), | ||
281 | )); | ||
282 | } | 302 | } |
303 | } | ||
283 | 304 | ||
284 | Ok(()) | 305 | impl ops::DerefMut for JodChild { |
306 | fn deref_mut(&mut self) -> &mut process::Child { | ||
307 | &mut self.0 | ||
308 | } | ||
309 | } | ||
310 | |||
311 | impl Drop for JodChild { | ||
312 | fn drop(&mut self) { | ||
313 | let _ = self.0.kill(); | ||
314 | } | ||
285 | } | 315 | } |
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index c21d75be0..157c7b665 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs | |||
@@ -1,15 +1,12 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, NameOwner, VisibilityOwner}, | 2 | ast::{self, NameOwner, VisibilityOwner}, |
3 | AstNode, | 3 | AstNode, |
4 | SyntaxKind::{ | 4 | SyntaxKind::{CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STRUCT_DEF, TRAIT_DEF, VISIBILITY}, |
5 | ATTR, COMMENT, CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STRUCT_DEF, TRAIT_DEF, VISIBILITY, | 5 | T, |
6 | WHITESPACE, | ||
7 | }, | ||
8 | SyntaxNode, TextSize, T, | ||
9 | }; | 6 | }; |
10 | use test_utils::mark; | 7 | use test_utils::mark; |
11 | 8 | ||
12 | use crate::{AssistContext, AssistId, Assists}; | 9 | use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; |
13 | 10 | ||
14 | // Assist: change_visibility | 11 | // Assist: change_visibility |
15 | // | 12 | // |
@@ -30,9 +27,8 @@ pub(crate) fn change_visibility(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
30 | } | 27 | } |
31 | 28 | ||
32 | fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 29 | fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
33 | let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { | 30 | let item_keyword = ctx.token_at_offset().find(|leaf| { |
34 | T![const] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true, | 31 | matches!(leaf.kind(), T![const] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait]) |
35 | _ => false, | ||
36 | }); | 32 | }); |
37 | 33 | ||
38 | let (offset, target) = if let Some(keyword) = item_keyword { | 34 | let (offset, target) = if let Some(keyword) = item_keyword { |
@@ -71,17 +67,6 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
71 | }) | 67 | }) |
72 | } | 68 | } |
73 | 69 | ||
74 | fn vis_offset(node: &SyntaxNode) -> TextSize { | ||
75 | node.children_with_tokens() | ||
76 | .skip_while(|it| match it.kind() { | ||
77 | WHITESPACE | COMMENT | ATTR => true, | ||
78 | _ => false, | ||
79 | }) | ||
80 | .next() | ||
81 | .map(|it| it.text_range().start()) | ||
82 | .unwrap_or_else(|| node.text_range().start()) | ||
83 | } | ||
84 | |||
85 | fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { | 70 | fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { |
86 | if vis.syntax().text() == "pub" { | 71 | if vis.syntax().text() == "pub" { |
87 | let target = vis.syntax().text_range(); | 72 | let target = vis.syntax().text_range(); |
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs index 54601d1f3..19d4dac5e 100644 --- a/crates/ra_assists/src/handlers/fix_visibility.rs +++ b/crates/ra_assists/src/handlers/fix_visibility.rs | |||
@@ -1,12 +1,8 @@ | |||
1 | use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; | 1 | use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; |
2 | use ra_db::FileId; | 2 | use ra_db::FileId; |
3 | use ra_syntax::{ | 3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; |
4 | ast, AstNode, | ||
5 | SyntaxKind::{ATTR, COMMENT, WHITESPACE}, | ||
6 | SyntaxNode, TextRange, TextSize, | ||
7 | }; | ||
8 | 4 | ||
9 | use crate::{AssistContext, AssistId, Assists}; | 5 | use crate::{utils::vis_offset, AssistContext, AssistId, Assists}; |
10 | 6 | ||
11 | // FIXME: this really should be a fix for diagnostic, rather than an assist. | 7 | // FIXME: this really should be a fix for diagnostic, rather than an assist. |
12 | 8 | ||
@@ -177,17 +173,6 @@ fn target_data_for_def( | |||
177 | Some((offset, target, target_file, target_name)) | 173 | Some((offset, target, target_file, target_name)) |
178 | } | 174 | } |
179 | 175 | ||
180 | fn vis_offset(node: &SyntaxNode) -> TextSize { | ||
181 | node.children_with_tokens() | ||
182 | .skip_while(|it| match it.kind() { | ||
183 | WHITESPACE | COMMENT | ATTR => true, | ||
184 | _ => false, | ||
185 | }) | ||
186 | .next() | ||
187 | .map(|it| it.text_range().start()) | ||
188 | .unwrap_or_else(|| node.text_range().start()) | ||
189 | } | ||
190 | |||
191 | #[cfg(test)] | 176 | #[cfg(test)] |
192 | mod tests { | 177 | mod tests { |
193 | use crate::tests::{check_assist, check_assist_not_applicable}; | 178 | use crate::tests::{check_assist, check_assist_not_applicable}; |
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index ca04ec671..90ce66378 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs | |||
@@ -81,10 +81,7 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
81 | } | 81 | } |
82 | 82 | ||
83 | fn contains_placeholder(a: &ast::MatchArm) -> bool { | 83 | fn contains_placeholder(a: &ast::MatchArm) -> bool { |
84 | match a.pat() { | 84 | matches!(a.pat(), Some(ast::Pat::PlaceholderPat(..))) |
85 | Some(ra_syntax::ast::Pat::PlaceholderPat(..)) => true, | ||
86 | _ => false, | ||
87 | } | ||
88 | } | 85 | } |
89 | 86 | ||
90 | #[cfg(test)] | 87 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index b7c45a619..02de902d6 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -7,7 +7,9 @@ use hir::{Adt, Crate, Enum, ScopeDef, Semantics, Trait, Type}; | |||
7 | use ra_ide_db::RootDatabase; | 7 | use ra_ide_db::RootDatabase; |
8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
9 | ast::{self, make, NameOwner}, | 9 | ast::{self, make, NameOwner}, |
10 | AstNode, SyntaxNode, T, | 10 | AstNode, |
11 | SyntaxKind::*, | ||
12 | SyntaxNode, TextSize, T, | ||
11 | }; | 13 | }; |
12 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
13 | 15 | ||
@@ -120,6 +122,13 @@ pub(crate) fn resolve_target_trait( | |||
120 | } | 122 | } |
121 | } | 123 | } |
122 | 124 | ||
125 | pub(crate) fn vis_offset(node: &SyntaxNode) -> TextSize { | ||
126 | node.children_with_tokens() | ||
127 | .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR)) | ||
128 | .map(|it| it.text_range().start()) | ||
129 | .unwrap_or_else(|| node.text_range().start()) | ||
130 | } | ||
131 | |||
123 | pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { | 132 | pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { |
124 | if let Some(expr) = invert_special_case(&expr) { | 133 | if let Some(expr) = invert_special_case(&expr) { |
125 | return expr; | 134 | return expr; |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 407322dc1..d6df48db2 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -27,8 +27,8 @@ test_utils = { path = "../test_utils" } | |||
27 | 27 | ||
28 | scoped-tls = "1" | 28 | scoped-tls = "1" |
29 | 29 | ||
30 | chalk-solve = { version = "0.15.0-dev.0", git = "https://github.com/rust-lang/chalk" } | 30 | chalk-solve = { version = "0.15.0" } |
31 | chalk-ir = { version = "0.15.0-dev.0", git = "https://github.com/rust-lang/chalk" } | 31 | chalk-ir = { version = "0.15.0" } |
32 | 32 | ||
33 | [dev-dependencies] | 33 | [dev-dependencies] |
34 | insta = "0.16.0" | 34 | insta = "0.16.0" |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 61af5f064..22884522a 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -785,11 +785,7 @@ impl<'a> InferenceContext<'a> { | |||
785 | for &check_closures in &[false, true] { | 785 | for &check_closures in &[false, true] { |
786 | let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); | 786 | let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); |
787 | for (&arg, param_ty) in args.iter().zip(param_iter) { | 787 | for (&arg, param_ty) in args.iter().zip(param_iter) { |
788 | let is_closure = match &self.body[arg] { | 788 | let is_closure = matches!(&self.body[arg], Expr::Lambda { .. }); |
789 | Expr::Lambda { .. } => true, | ||
790 | _ => false, | ||
791 | }; | ||
792 | |||
793 | if is_closure != check_closures { | 789 | if is_closure != check_closures { |
794 | continue; | 790 | continue; |
795 | } | 791 | } |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 414158139..c9513b752 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -620,17 +620,11 @@ pub enum GenericPredicate { | |||
620 | 620 | ||
621 | impl GenericPredicate { | 621 | impl GenericPredicate { |
622 | pub fn is_error(&self) -> bool { | 622 | pub fn is_error(&self) -> bool { |
623 | match self { | 623 | matches!(self, GenericPredicate::Error) |
624 | GenericPredicate::Error => true, | ||
625 | _ => false, | ||
626 | } | ||
627 | } | 624 | } |
628 | 625 | ||
629 | pub fn is_implemented(&self) -> bool { | 626 | pub fn is_implemented(&self) -> bool { |
630 | match self { | 627 | matches!(self, GenericPredicate::Implemented(_)) |
631 | GenericPredicate::Implemented(_) => true, | ||
632 | _ => false, | ||
633 | } | ||
634 | } | 628 | } |
635 | 629 | ||
636 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { | 630 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 98fb34486..c87652555 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -313,10 +313,8 @@ fn get_string_representation(expr: &ast::Expr) -> Option<String> { | |||
313 | } | 313 | } |
314 | 314 | ||
315 | fn is_obvious_param(param_name: &str) -> bool { | 315 | fn is_obvious_param(param_name: &str) -> bool { |
316 | let is_obvious_param_name = match param_name { | 316 | let is_obvious_param_name = |
317 | "predicate" | "value" | "pat" | "rhs" | "other" => true, | 317 | matches!(param_name, "predicate" | "value" | "pat" | "rhs" | "other"); |
318 | _ => false, | ||
319 | }; | ||
320 | param_name.len() == 1 || is_obvious_param_name | 318 | param_name.len() == 1 || is_obvious_param_name |
321 | } | 319 | } |
322 | 320 | ||
diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs index 5036c1fb0..6907c09e8 100644 --- a/crates/ra_ide/src/join_lines.rs +++ b/crates/ra_ide/src/join_lines.rs | |||
@@ -165,10 +165,7 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Opti | |||
165 | } | 165 | } |
166 | 166 | ||
167 | fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { | 167 | fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { |
168 | match (left, right) { | 168 | matches!((left, right), (T![,], T![')']) | (T![,], T![']'])) |
169 | (T![,], T![')']) | (T![,], T![']']) => true, | ||
170 | _ => false, | ||
171 | } | ||
172 | } | 169 | } |
173 | 170 | ||
174 | #[cfg(test)] | 171 | #[cfg(test)] |
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index 6929055b2..5a09e7d1d 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs | |||
@@ -346,10 +346,7 @@ impl Query { | |||
346 | } | 346 | } |
347 | 347 | ||
348 | fn is_type(kind: SyntaxKind) -> bool { | 348 | fn is_type(kind: SyntaxKind) -> bool { |
349 | match kind { | 349 | matches!(kind, STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF) |
350 | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => true, | ||
351 | _ => false, | ||
352 | } | ||
353 | } | 350 | } |
354 | 351 | ||
355 | /// The actual data that is stored in the index. It should be as compact as | 352 | /// The actual data that is stored in the index. It should be as compact as |
diff --git a/crates/ra_mbe/src/parser.rs b/crates/ra_mbe/src/parser.rs index 034150432..1e5dafbdf 100644 --- a/crates/ra_mbe/src/parser.rs +++ b/crates/ra_mbe/src/parser.rs | |||
@@ -137,10 +137,7 @@ fn eat_fragment_kind<'a>( | |||
137 | } | 137 | } |
138 | 138 | ||
139 | fn is_boolean_literal(lit: &tt::Literal) -> bool { | 139 | fn is_boolean_literal(lit: &tt::Literal) -> bool { |
140 | match lit.text.as_str() { | 140 | matches!(lit.text.as_str(), "true" | "false") |
141 | "true" | "false" => true, | ||
142 | _ => false, | ||
143 | } | ||
144 | } | 141 | } |
145 | 142 | ||
146 | fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ExpandError> { | 143 | fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ExpandError> { |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 293baecf6..caedeead0 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -73,10 +73,7 @@ pub(crate) mod fragments { | |||
73 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] | 73 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] |
74 | pub(crate) fn meta_item(p: &mut Parser) { | 74 | pub(crate) fn meta_item(p: &mut Parser) { |
75 | fn is_delimiter(p: &mut Parser) -> bool { | 75 | fn is_delimiter(p: &mut Parser) -> bool { |
76 | match p.current() { | 76 | matches!(p.current(), T!['{'] | T!['('] | T!['[']) |
77 | T!['{'] | T!['('] | T!['['] => true, | ||
78 | _ => false, | ||
79 | } | ||
80 | } | 77 | } |
81 | 78 | ||
82 | if is_delimiter(p) { | 79 | if is_delimiter(p) { |
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index fd51189d5..b503af1dc 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs | |||
@@ -41,10 +41,7 @@ fn path(p: &mut Parser, mode: Mode) { | |||
41 | path_segment(p, mode, true); | 41 | path_segment(p, mode, true); |
42 | let mut qual = path.complete(p, PATH); | 42 | let mut qual = path.complete(p, PATH); |
43 | loop { | 43 | loop { |
44 | let use_tree = match p.nth(2) { | 44 | let use_tree = matches!(p.nth(2), T![*] | T!['{']); |
45 | T![*] | T!['{'] => true, | ||
46 | _ => false, | ||
47 | }; | ||
48 | if p.at(T![::]) && !use_tree { | 45 | if p.at(T![::]) && !use_tree { |
49 | let path = qual.precede(p); | 46 | let path = qual.precede(p); |
50 | p.bump(T![::]); | 47 | p.bump(T![::]); |
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 325d566ad..d1330d4b9 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs | |||
@@ -169,10 +169,7 @@ fn is_where_predicate(p: &mut Parser) -> bool { | |||
169 | } | 169 | } |
170 | 170 | ||
171 | fn is_where_clause_end(p: &mut Parser) -> bool { | 171 | fn is_where_clause_end(p: &mut Parser) -> bool { |
172 | match p.current() { | 172 | matches!(p.current(), T!['{'] | T![;] | T![=]) |
173 | T!['{'] | T![;] | T![=] => true, | ||
174 | _ => false, | ||
175 | } | ||
176 | } | 173 | } |
177 | 174 | ||
178 | fn where_predicate(p: &mut Parser) { | 175 | fn where_predicate(p: &mut Parser) { |
diff --git a/crates/ra_parser/src/syntax_kind.rs b/crates/ra_parser/src/syntax_kind.rs index 8d6bd057b..63204436c 100644 --- a/crates/ra_parser/src/syntax_kind.rs +++ b/crates/ra_parser/src/syntax_kind.rs | |||
@@ -20,9 +20,6 @@ impl From<SyntaxKind> for u16 { | |||
20 | 20 | ||
21 | impl SyntaxKind { | 21 | impl SyntaxKind { |
22 | pub fn is_trivia(self) -> bool { | 22 | pub fn is_trivia(self) -> bool { |
23 | match self { | 23 | matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) |
24 | SyntaxKind::WHITESPACE | SyntaxKind::COMMENT => true, | ||
25 | _ => false, | ||
26 | } | ||
27 | } | 24 | } |
28 | } | 25 | } |
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 7771d6759..db5438d68 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs | |||
@@ -399,10 +399,7 @@ impl ast::BlockExpr { | |||
399 | Some(it) => it, | 399 | Some(it) => it, |
400 | None => return true, | 400 | None => return true, |
401 | }; | 401 | }; |
402 | match parent.kind() { | 402 | !matches!(parent.kind(), FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR) |
403 | FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false, | ||
404 | _ => true, | ||
405 | } | ||
406 | } | 403 | } |
407 | } | 404 | } |
408 | 405 | ||
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index 98c38d009..662c6f73e 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -459,16 +459,16 @@ impl ast::RangePat { | |||
459 | 459 | ||
460 | impl ast::TokenTree { | 460 | impl ast::TokenTree { |
461 | pub fn left_delimiter_token(&self) -> Option<SyntaxToken> { | 461 | pub fn left_delimiter_token(&self) -> Option<SyntaxToken> { |
462 | self.syntax().first_child_or_token()?.into_token().filter(|it| match it.kind() { | 462 | self.syntax() |
463 | T!['{'] | T!['('] | T!['['] => true, | 463 | .first_child_or_token()? |
464 | _ => false, | 464 | .into_token() |
465 | }) | 465 | .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['['])) |
466 | } | 466 | } |
467 | 467 | ||
468 | pub fn right_delimiter_token(&self) -> Option<SyntaxToken> { | 468 | pub fn right_delimiter_token(&self) -> Option<SyntaxToken> { |
469 | self.syntax().last_child_or_token()?.into_token().filter(|it| match it.kind() { | 469 | self.syntax() |
470 | T!['}'] | T![')'] | T![']'] => true, | 470 | .last_child_or_token()? |
471 | _ => false, | 471 | .into_token() |
472 | }) | 472 | .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']'])) |
473 | } | 473 | } |
474 | } | 474 | } |
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs index edbc190f8..ed5a42ea3 100644 --- a/crates/ra_syntax/src/parsing/reparsing.rs +++ b/crates/ra_syntax/src/parsing/reparsing.rs | |||
@@ -120,10 +120,7 @@ fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String { | |||
120 | } | 120 | } |
121 | 121 | ||
122 | fn is_contextual_kw(text: &str) -> bool { | 122 | fn is_contextual_kw(text: &str) -> bool { |
123 | match text { | 123 | matches!(text, "auto" | "default" | "union") |
124 | "auto" | "default" | "union" => true, | ||
125 | _ => false, | ||
126 | } | ||
127 | } | 124 | } |
128 | 125 | ||
129 | fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> { | 126 | fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> { |
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs index 5967f44cd..02c771f70 100644 --- a/crates/ra_tt/src/buffer.rs +++ b/crates/ra_tt/src/buffer.rs | |||
@@ -105,10 +105,7 @@ impl<'a> Eq for Cursor<'a> {} | |||
105 | impl<'a> Cursor<'a> { | 105 | impl<'a> Cursor<'a> { |
106 | /// Check whether it is eof | 106 | /// Check whether it is eof |
107 | pub fn eof(self) -> bool { | 107 | pub fn eof(self) -> bool { |
108 | match self.buffer.entry(&self.ptr) { | 108 | matches!(self.buffer.entry(&self.ptr), None | Some(Entry::End(None))) |
109 | None | Some(Entry::End(None)) => true, | ||
110 | _ => false, | ||
111 | } | ||
112 | } | 109 | } |
113 | 110 | ||
114 | /// If the cursor is pointing at the end of a subtree, returns | 111 | /// If the cursor is pointing at the end of a subtree, returns |
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index 39ce77900..c5faec83a 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs | |||
@@ -28,16 +28,10 @@ pub enum Verbosity { | |||
28 | 28 | ||
29 | impl Verbosity { | 29 | impl Verbosity { |
30 | pub fn is_verbose(self) -> bool { | 30 | pub fn is_verbose(self) -> bool { |
31 | match self { | 31 | matches!(self, Verbosity::Verbose | Verbosity::Spammy) |
32 | Verbosity::Verbose | Verbosity::Spammy => true, | ||
33 | _ => false, | ||
34 | } | ||
35 | } | 32 | } |
36 | pub fn is_spammy(self) -> bool { | 33 | pub fn is_spammy(self) -> bool { |
37 | match self { | 34 | matches!(self, Verbosity::Spammy) |
38 | Verbosity::Spammy => true, | ||
39 | _ => false, | ||
40 | } | ||
41 | } | 35 | } |
42 | } | 36 | } |
43 | 37 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 4fe99ff68..930375d3e 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -78,10 +78,7 @@ pub fn analysis_bench( | |||
78 | } | 78 | } |
79 | } | 79 | } |
80 | BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => { | 80 | BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => { |
81 | let is_completion = match what { | 81 | let is_completion = matches!(what, BenchWhat::Complete(..)); |
82 | BenchWhat::Complete(..) => true, | ||
83 | _ => false, | ||
84 | }; | ||
85 | 82 | ||
86 | let offset = host | 83 | let offset = host |
87 | .analysis() | 84 | .analysis() |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index e5194fe41..9fd16ef3b 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -216,7 +216,11 @@ impl GlobalState { | |||
216 | flycheck::Progress::DidCheckCrate(target) => { | 216 | flycheck::Progress::DidCheckCrate(target) => { |
217 | (Progress::Report, Some(target)) | 217 | (Progress::Report, Some(target)) |
218 | } | 218 | } |
219 | flycheck::Progress::DidFinish | flycheck::Progress::DidCancel => { | 219 | flycheck::Progress::DidCancel => (Progress::End, None), |
220 | flycheck::Progress::DidFinish(result) => { | ||
221 | if let Err(err) = result { | ||
222 | log::error!("cargo check failed: {}", err) | ||
223 | } | ||
220 | (Progress::End, None) | 224 | (Progress::End, None) |
221 | } | 225 | } |
222 | }; | 226 | }; |
diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index 25ba8d798..b1ea298ae 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs | |||
@@ -10,7 +10,7 @@ mod include; | |||
10 | 10 | ||
11 | use std::convert::{TryFrom, TryInto}; | 11 | use std::convert::{TryFrom, TryInto}; |
12 | 12 | ||
13 | use crossbeam_channel::{select, unbounded, Receiver}; | 13 | use crossbeam_channel::{select, unbounded, Receiver, Sender}; |
14 | use notify::{RecommendedWatcher, RecursiveMode, Watcher}; | 14 | use notify::{RecommendedWatcher, RecursiveMode, Watcher}; |
15 | use paths::{AbsPath, AbsPathBuf}; | 15 | use paths::{AbsPath, AbsPathBuf}; |
16 | use rustc_hash::FxHashSet; | 16 | use rustc_hash::FxHashSet; |
@@ -22,8 +22,8 @@ use crate::include::Include; | |||
22 | #[derive(Debug)] | 22 | #[derive(Debug)] |
23 | pub struct NotifyHandle { | 23 | pub struct NotifyHandle { |
24 | // Relative order of fields below is significant. | 24 | // Relative order of fields below is significant. |
25 | sender: crossbeam_channel::Sender<Message>, | 25 | sender: Sender<Message>, |
26 | _thread: jod_thread::JoinHandle, | 26 | thread: jod_thread::JoinHandle, |
27 | } | 27 | } |
28 | 28 | ||
29 | #[derive(Debug)] | 29 | #[derive(Debug)] |
@@ -37,7 +37,7 @@ impl loader::Handle for NotifyHandle { | |||
37 | let actor = NotifyActor::new(sender); | 37 | let actor = NotifyActor::new(sender); |
38 | let (sender, receiver) = unbounded::<Message>(); | 38 | let (sender, receiver) = unbounded::<Message>(); |
39 | let thread = jod_thread::spawn(move || actor.run(receiver)); | 39 | let thread = jod_thread::spawn(move || actor.run(receiver)); |
40 | NotifyHandle { sender, _thread: thread } | 40 | NotifyHandle { sender, thread } |
41 | } | 41 | } |
42 | fn set_config(&mut self, config: loader::Config) { | 42 | fn set_config(&mut self, config: loader::Config) { |
43 | self.sender.send(Message::Config(config)).unwrap() | 43 | self.sender.send(Message::Config(config)).unwrap() |