Repository: rust-analyzer/rust-analyzer
Pull request #4812 (2020-06-09 11:14:14)

Use correct indent when replacing with match


bors r+
🤖


Patch:
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs
index 4cc75a7ce2..dfade74321 100644
--- a/crates/ra_assists/src/handlers/early_return.rs
+++ b/crates/ra_assists/src/handlers/early_return.rs
@@ -154,7 +154,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
             parent_block: &ast::BlockExpr,
             if_expr: &ast::IfExpr,
         ) -> SyntaxNode {
-            let then_block_items = then_block.dedent(IndentLevel::from(1));
+            let then_block_items = then_block.dedent(IndentLevel(1));
             let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
             let end_of_then =
                 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
index e016f51c3e..dfcd787de5 100644
--- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
@@ -51,6 +51,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
     acc.add(AssistId("replace_if_let_with_match"), "Replace with match", target, move |edit| {
         let match_expr = {
             let then_arm = {
+                let then_block = then_block.reset_indent().indent(IndentLevel(1));
                 let then_expr = unwrap_trivial_block(then_block);
                 make::match_arm(vec![pat.clone()], then_expr)
             };
@@ -64,8 +65,8 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
                 let else_expr = unwrap_trivial_block(else_block);
                 make::match_arm(vec![pattern], else_expr)
             };
-            make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm]))
-                .indent(IndentLevel::from_node(if_expr.syntax()))
+            let match_expr = make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm]));
+            match_expr.indent(IndentLevel::from_node(if_expr.syntax()))
         };
 
         edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr);
@@ -213,4 +214,36 @@ fn foo(x: Result<i32, ()>) {
            "#,
         );
     }
+
+    #[test]
+    fn nested_indent() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+fn main() {
+    if true {
+        <|>if let Ok(rel_path) = path.strip_prefix(root_path) {
+            let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
+            Some((*id, rel_path))
+        } else {
+            None
+        }
+    }
+}
+"#,
+            r#"
+fn main() {
+    if true {
+        match path.strip_prefix(root_path) {
+            Ok(rel_path) => {
+                let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
+                Some((*id, rel_path))
+            }
+            _ => None,
+        }
+    }
+}
+"#,
+        )
+    }
 }
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 97642bc244..9c14b954af 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -121,12 +121,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
             T![unsafe] => {
                 // test default_unsafe_impl
                 // default unsafe impl Foo {}
-
-                // test default_unsafe_fn
-                // impl T for Foo {
-                //     default unsafe fn foo() {}
-                // }
-                if p.nth(2) == T![impl] || p.nth(2) == T![fn] {
+                if p.nth(2) == T![impl] {
                     p.bump_remap(T![default]);
                     p.bump(T![unsafe]);
                     has_mods = true;
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs
index ee2de4c256..09c06fef93 100644
--- a/crates/ra_project_model/src/json_project.rs
+++ b/crates/ra_project_model/src/json_project.rs
@@ -2,7 +2,7 @@
 
 use std::path::PathBuf;
 
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
 use serde::Deserialize;
 
 /// Roots and crates that compose this Rust project.
@@ -28,9 +28,16 @@ pub struct Crate {
     pub(crate) edition: Edition,
     pub(crate) deps: Vec<Dep>,
 
+    // This is the preferred method of providing cfg options.
     #[serde(default)]
     pub(crate) cfg: FxHashSet<String>,
 
+    // These two are here for transition only.
+    #[serde(default)]
+    pub(crate) atom_cfgs: FxHashSet<String>,
+    #[serde(default)]
+    pub(crate) key_value_cfgs: FxHashMap<String, String>,
+
     pub(crate) out_dir: Option<PathBuf>,
     pub(crate) proc_macro_dylib_path: Option<PathBuf>,
 }
@@ -92,4 +99,37 @@ mod tests {
         assert!(krate.cfg.contains(&"feature=feature_2".to_string()));
         assert!(krate.cfg.contains(&"other=value".to_string()));
     }
+
+    #[test]
+    fn test_crate_deserialization_old_json() {
+        let raw_json = json!(    {
+           "crate_id": 2,
+           "root_module": "this/is/a/file/path.rs",
+           "deps": [
+             {
+               "crate": 1,
+               "name": "some_dep_crate"
+             },
+           ],
+           "edition": "2015",
+           "atom_cfgs": [
+             "atom_1",
+             "atom_2",
+           ],
+           "key_value_cfgs": {
+             "feature": "feature_1",
+             "feature": "feature_2",
+             "other": "value",
+           },
+        });
+
+        let krate: Crate = serde_json::from_value(raw_json).unwrap();
+
+        assert!(krate.atom_cfgs.contains(&"atom_1".to_string()));
+        assert!(krate.atom_cfgs.contains(&"atom_2".to_string()));
+        assert!(krate.key_value_cfgs.contains_key(&"feature".to_string()));
+        assert_eq!(krate.key_value_cfgs.get("feature"), Some(&"feature_2".to_string()));
+        assert!(krate.key_value_cfgs.contains_key(&"other".to_string()));
+        assert_eq!(krate.key_value_cfgs.get("other"), Some(&"value".to_string()));
+    }
 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 47fa34ddfb..fe03b509e4 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -280,6 +280,12 @@ impl ProjectWorkspace {
                                     }
                                 }
                             }
+                            for name in &krate.atom_cfgs {
+                                opts.insert_atom(name.into());
+                            }
+                            for (key, value) in &krate.key_value_cfgs {
+                                opts.insert_key_value(key.into(), value.into());
+                            }
                             opts
                         };
 
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index 29eb3fcb9c..2ef173a039 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -579,12 +579,17 @@ pub trait AstNodeEdit: AstNode + Clone + Sized {
         rewriter.rewrite_ast(self)
     }
     #[must_use]
-    fn indent(&self, indent: IndentLevel) -> Self {
-        Self::cast(indent.increase_indent(self.syntax().clone())).unwrap()
+    fn indent(&self, level: IndentLevel) -> Self {
+        Self::cast(level.increase_indent(self.syntax().clone())).unwrap()
     }
     #[must_use]
-    fn dedent(&self, indent: IndentLevel) -> Self {
-        Self::cast(indent.decrease_indent(self.syntax().clone())).unwrap()
+    fn dedent(&self, level: IndentLevel) -> Self {
+        Self::cast(level.decrease_indent(self.syntax().clone())).unwrap()
+    }
+    #[must_use]
+    fn reset_indent(&self) -> Self {
+        let level = IndentLevel::from_node(self.syntax());
+        self.dedent(level)
     }
 }
 


Test patch:
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast
deleted file mode 100644
index adb6159f47..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rast
+++ /dev/null
@@ -1,40 +0,0 @@
-SOURCE_FILE@0..50
-  IMPL_DEF@0..49
-    IMPL_KW@0..4 "impl"
-    WHITESPACE@4..5 " "
-    PATH_TYPE@5..6
-      PATH@5..6
-        PATH_SEGMENT@5..6
-          NAME_REF@5..6
-            IDENT@5..6 "T"
-    WHITESPACE@6..7 " "
-    FOR_KW@7..10 "for"
-    WHITESPACE@10..11 " "
-    PATH_TYPE@11..14
-      PATH@11..14
-        PATH_SEGMENT@11..14
-          NAME_REF@11..14
-            IDENT@11..14 "Foo"
-    WHITESPACE@14..15 " "
-    ITEM_LIST@15..49
-      L_CURLY@15..16 "{"
-      WHITESPACE@16..21 "\n    "
-      FN_DEF@21..47
-        DEFAULT_KW@21..28 "default"
-        WHITESPACE@28..29 " "
-        UNSAFE_KW@29..35 "unsafe"
-        WHITESPACE@35..36 " "
-        FN_KW@36..38 "fn"
-        WHITESPACE@38..39 " "
-        NAME@39..42
-          IDENT@39..42 "foo"
-        PARAM_LIST@42..44
-          L_PAREN@42..43 "("
-          R_PAREN@43..44 ")"
-        WHITESPACE@44..45 " "
-        BLOCK_EXPR@45..47
-          L_CURLY@45..46 "{"
-          R_CURLY@46..47 "}"
-      WHITESPACE@47..48 "\n"
-      R_CURLY@48..49 "}"
-  WHITESPACE@49..50 "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rs b/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rs
deleted file mode 100644
index 12926cd8a1..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0163_default_unsafe_fn.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-impl T for Foo {
-    default unsafe fn foo() {}
-}