aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/handlers/fill_match_arms.rs44
-rw-r--r--crates/ra_assists/src/marks.rs1
-rw-r--r--crates/ra_assists/src/utils.rs35
3 files changed, 69 insertions, 11 deletions
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs
index 13c1e7e80..b57ff75ae 100644
--- a/crates/ra_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ra_assists/src/handlers/fill_match_arms.rs
@@ -4,8 +4,9 @@ use hir::{Adt, HasSource, ModuleDef, Semantics};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; 6use ra_syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
7use test_utils::tested_by;
7 8
8use crate::{AssistContext, AssistId, Assists}; 9use crate::{utils::FamousDefs, AssistContext, AssistId, Assists};
9 10
10// Assist: fill_match_arms 11// Assist: fill_match_arms
11// 12//
@@ -49,12 +50,18 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
49 let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { 50 let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) {
50 let variants = enum_def.variants(ctx.db); 51 let variants = enum_def.variants(ctx.db);
51 52
52 variants 53 let mut variants = variants
53 .into_iter() 54 .into_iter()
54 .filter_map(|variant| build_pat(ctx.db, module, variant)) 55 .filter_map(|variant| build_pat(ctx.db, module, variant))
55 .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat)) 56 .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat))
56 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) 57 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block()))
57 .collect() 58 .collect::<Vec<_>>();
59 if Some(enum_def) == FamousDefs(&ctx.sema, module.krate()).core_option_Option() {
60 // Match `Some` variant first.
61 tested_by!(option_order);
62 variants.reverse()
63 }
64 variants
58 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { 65 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) {
59 // Partial fill not currently supported for tuple of enums. 66 // Partial fill not currently supported for tuple of enums.
60 if !arms.is_empty() { 67 if !arms.is_empty() {
@@ -167,9 +174,13 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
167 174
168#[cfg(test)] 175#[cfg(test)]
169mod tests { 176mod tests {
170 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; 177 use crate::{
178 tests::{check_assist, check_assist_not_applicable, check_assist_target},
179 utils::FamousDefs,
180 };
171 181
172 use super::fill_match_arms; 182 use super::fill_match_arms;
183 use test_utils::covers;
173 184
174 #[test] 185 #[test]
175 fn all_match_arms_provided() { 186 fn all_match_arms_provided() {
@@ -736,4 +747,29 @@ mod tests {
736 "#, 747 "#,
737 ); 748 );
738 } 749 }
750
751 #[test]
752 fn option_order() {
753 covers!(option_order);
754 let before = r#"
755fn foo(opt: Option<i32>) {
756 match opt<|> {
757 }
758}"#;
759 let before =
760 &format!("//- main.rs crate:main deps:core\n{}{}", before, FamousDefs::FIXTURE);
761
762 check_assist(
763 fill_match_arms,
764 before,
765 r#"
766fn foo(opt: Option<i32>) {
767 match <|>opt {
768 Some(_) => {}
769 None => {}
770 }
771}
772"#,
773 );
774 }
739} 775}
diff --git a/crates/ra_assists/src/marks.rs b/crates/ra_assists/src/marks.rs
index d579e627f..722f3c6a4 100644
--- a/crates/ra_assists/src/marks.rs
+++ b/crates/ra_assists/src/marks.rs
@@ -1,6 +1,7 @@
1//! See test_utils/src/marks.rs 1//! See test_utils/src/marks.rs
2 2
3test_utils::marks![ 3test_utils::marks![
4 option_order
4 introduce_var_in_comment_is_not_applicable 5 introduce_var_in_comment_is_not_applicable
5 test_introduce_var_expr_stmt 6 test_introduce_var_expr_stmt
6 test_introduce_var_last_expr 7 test_introduce_var_last_expr
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 9af27180b..0038a9764 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -3,7 +3,7 @@ pub(crate) mod insert_use;
3 3
4use std::{iter, ops}; 4use std::{iter, ops};
5 5
6use hir::{Adt, Crate, Semantics, Trait, Type}; 6use hir::{Adt, Crate, Enum, ScopeDef, Semantics, Trait, Type};
7use ra_ide_db::RootDatabase; 7use ra_ide_db::RootDatabase;
8use ra_syntax::{ 8use ra_syntax::{
9 ast::{self, make, NameOwner}, 9 ast::{self, make, NameOwner},
@@ -200,13 +200,19 @@ impl FamousDefs<'_, '_> {
200 #[cfg(test)] 200 #[cfg(test)]
201 pub(crate) const FIXTURE: &'static str = r#" 201 pub(crate) const FIXTURE: &'static str = r#"
202//- /libcore.rs crate:core 202//- /libcore.rs crate:core
203pub mod convert{ 203pub mod convert {
204 pub trait From<T> { 204 pub trait From<T> {
205 fn from(T) -> Self; 205 fn from(T) -> Self;
206 } 206 }
207} 207}
208 208
209pub mod prelude { pub use crate::convert::From } 209pub mod option {
210 pub enum Option<T> { None, Some(T)}
211}
212
213pub mod prelude {
214 pub use crate::{convert::From, option::Option::{self, *}};
215}
210#[prelude_import] 216#[prelude_import]
211pub use prelude::*; 217pub use prelude::*;
212"#; 218"#;
@@ -215,7 +221,25 @@ pub use prelude::*;
215 self.find_trait("core:convert:From") 221 self.find_trait("core:convert:From")
216 } 222 }
217 223
224 pub(crate) fn core_option_Option(&self) -> Option<Enum> {
225 self.find_enum("core:option:Option")
226 }
227
218 fn find_trait(&self, path: &str) -> Option<Trait> { 228 fn find_trait(&self, path: &str) -> Option<Trait> {
229 match self.find_def(path)? {
230 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
231 _ => None,
232 }
233 }
234
235 fn find_enum(&self, path: &str) -> Option<Enum> {
236 match self.find_def(path)? {
237 hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
238 _ => None,
239 }
240 }
241
242 fn find_def(&self, path: &str) -> Option<ScopeDef> {
219 let db = self.0.db; 243 let db = self.0.db;
220 let mut path = path.split(':'); 244 let mut path = path.split(':');
221 let trait_ = path.next_back()?; 245 let trait_ = path.next_back()?;
@@ -240,9 +264,6 @@ pub use prelude::*;
240 } 264 }
241 let def = 265 let def =
242 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; 266 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1;
243 match def { 267 Some(def)
244 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
245 _ => None,
246 }
247 } 268 }
248} 269}