]> git.lizzy.rs Git - rust.git/commitdiff
Add `find_impl_block_end` assist helper
authorYoshua Wuyts <yoshuawuyts@gmail.com>
Fri, 12 Feb 2021 10:48:43 +0000 (11:48 +0100)
committerYoshua Wuyts <yoshuawuyts@gmail.com>
Fri, 12 Feb 2021 16:59:08 +0000 (17:59 +0100)
crates/assists/src/handlers/generate_enum_match_method.rs
crates/assists/src/handlers/generate_getter.rs
crates/assists/src/handlers/generate_getter_mut.rs
crates/assists/src/handlers/generate_new.rs
crates/assists/src/handlers/generate_setter.rs
crates/assists/src/utils.rs

index c3ff38b6668290499be114e6c6a317be505c40f2..aeb887e717c17dc7585d16e9cb05b55e681a5fc7 100644 (file)
@@ -4,7 +4,7 @@
 use test_utils::mark;
 
 use crate::{
-    utils::{find_impl_block, find_struct_impl, generate_impl_text},
+    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -80,7 +80,7 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext)
             );
 
             let start_offset = impl_def
-                .and_then(|impl_def| find_impl_block(impl_def, &mut buf))
+                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                 .unwrap_or_else(|| {
                     buf = generate_impl_text(&ast::Adt::Enum(parent_enum.clone()), &buf);
                     parent_enum.syntax().text_range().end()
@@ -197,6 +197,43 @@ impl Variant {
     pub(crate) fn is_minor(&self) -> bool {
         matches!(self, Self::Minor)
     }
+}"#,
+        );
+    }
+
+    #[test]
+    fn test_multiple_generate_enum_match_from_variant() {
+        check_assist(
+            generate_enum_match_method,
+            r#"
+enum Variant {
+    Undefined,
+    Minor,
+    Major$0,
+}
+
+impl Variant {
+    /// Returns `true` if the variant is [`Minor`].
+    fn is_minor(&self) -> bool {
+        matches!(self, Self::Minor)
+    }
+}"#,
+            r#"enum Variant {
+    Undefined,
+    Minor,
+    Major,
+}
+
+impl Variant {
+    /// Returns `true` if the variant is [`Minor`].
+    fn is_minor(&self) -> bool {
+        matches!(self, Self::Minor)
+    }
+
+    /// Returns `true` if the variant is [`Major`].
+    fn is_major(&self) -> bool {
+        matches!(self, Self::Major)
+    }
 }"#,
         );
     }
index b63dfce4194e1b9ecab013f935c09d565221f555..fbcf8b0699fa2fb0877e2ed3417b8f6f68460f18 100644 (file)
@@ -3,7 +3,7 @@
 use syntax::ast::{self, AstNode, NameOwner};
 
 use crate::{
-    utils::{find_impl_block, find_struct_impl, generate_impl_text},
+    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -73,7 +73,7 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<
             );
 
             let start_offset = impl_def
-                .and_then(|impl_def| find_impl_block(impl_def, &mut buf))
+                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                 .unwrap_or_else(|| {
                     buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
                     strukt.syntax().text_range().end()
@@ -150,6 +150,42 @@ impl<T: Clone> Context<T> {
     pub(crate) fn data(&self) -> &T {
         &self.data
     }
+}"#,
+        );
+    }
+
+    #[test]
+    fn test_multiple_generate_getter() {
+        check_assist(
+            generate_getter,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Get a reference to the context's data.
+    fn data(&self) -> &T {
+        &self.data
+    }
+}"#,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    count: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Get a reference to the context's data.
+    fn data(&self) -> &T {
+        &self.data
+    }
+
+    /// Get a reference to the context's count.
+    fn count(&self) -> &usize {
+        &self.count
+    }
 }"#,
         );
     }
index b5085035e0aef292cb0218950385e41d67da0185..bf0d99881fae931798af9819ff7cc6678cce2dc9 100644 (file)
@@ -3,7 +3,7 @@
 use syntax::ast::{self, AstNode, NameOwner};
 
 use crate::{
-    utils::{find_impl_block, find_struct_impl, generate_impl_text},
+    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -76,7 +76,7 @@ pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext) -> Opt
             );
 
             let start_offset = impl_def
-                .and_then(|impl_def| find_impl_block(impl_def, &mut buf))
+                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                 .unwrap_or_else(|| {
                     buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
                     strukt.syntax().text_range().end()
@@ -153,6 +153,42 @@ impl<T: Clone> Context<T> {
     pub(crate) fn data_mut(&mut self) -> &mut T {
         &mut self.data
     }
+}"#,
+        );
+    }
+
+    #[test]
+    fn test_multiple_generate_getter_mut() {
+        check_assist(
+            generate_getter_mut,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Get a mutable reference to the context's data.
+    fn data_mut(&mut self) -> &mut T {
+        &mut self.data
+    }
+}"#,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    count: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Get a mutable reference to the context's data.
+    fn data_mut(&mut self) -> &mut T {
+        &mut self.data
+    }
+
+    /// Get a mutable reference to the context's count.
+    fn count_mut(&mut self) -> &mut usize {
+        &mut self.count
+    }
 }"#,
         );
     }
index c29077225cda54d0768b6799e5e0d3cc52850cff..8ce5930b77dc34bed68ddbfb7a97af1f97e9a8e6 100644 (file)
@@ -4,7 +4,7 @@
 use syntax::ast::{self, AstNode, NameOwner, StructKind, VisibilityOwner};
 
 use crate::{
-    utils::{find_impl_block, find_struct_impl, generate_impl_text},
+    utils::{find_impl_block_start, find_struct_impl, generate_impl_text},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -58,7 +58,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
         format_to!(buf, "    {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
 
         let start_offset = impl_def
-            .and_then(|impl_def| find_impl_block(impl_def, &mut buf))
+            .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
             .unwrap_or_else(|| {
                 buf = generate_impl_text(&Adt::Struct(strukt.clone()), &buf);
                 strukt.syntax().text_range().end()
index c9043a16297d9a75a45341b8db14793aba74e957..b655f9b9cd99854a11a14d664971a1d986730aee 100644 (file)
@@ -3,7 +3,7 @@
 use syntax::ast::{self, AstNode, NameOwner};
 
 use crate::{
-    utils::{find_impl_block, find_struct_impl, generate_impl_text},
+    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -79,7 +79,7 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext) -> Option<
             );
 
             let start_offset = impl_def
-                .and_then(|impl_def| find_impl_block(impl_def, &mut buf))
+                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                 .unwrap_or_else(|| {
                     buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
                     strukt.syntax().text_range().end()
@@ -156,6 +156,42 @@ impl<T: Clone> Person<T> {
     pub(crate) fn set_data(&mut self, data: T) {
         self.data = data;
     }
+}"#,
+        );
+    }
+
+    #[test]
+    fn test_multiple_generate_setter() {
+        check_assist(
+            generate_setter,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    cou$0nt: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Set the context's data.
+    fn set_data(&mut self, data: T) {
+        self.data = data;
+    }
+}"#,
+            r#"
+struct Context<T: Clone> {
+    data: T,
+    count: usize,
+}
+
+impl<T: Clone> Context<T> {
+    /// Set the context's data.
+    fn set_data(&mut self, data: T) {
+        self.data = data;
+    }
+
+    /// Set the context's count.
+    fn set_count(&mut self, count: usize) {
+        self.count = count;
+    }
 }"#,
         );
     }
index 643dade238b6fbb9cfba7768286ec9bb8d778d2d..5dd32aef103b0ad434c39ed2f0e6bb1e861063cc 100644 (file)
@@ -279,7 +279,7 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
 //
 // FIXME: change the new fn checking to a more semantic approach when that's more
 // viable (e.g. we process proc macros, etc)
-// FIXME: this partially overlaps with `find_impl_block`
+// FIXME: this partially overlaps with `find_impl_block_*`
 pub(crate) fn find_struct_impl(
     ctx: &AssistContext,
     strukt: &ast::Adt,
@@ -343,17 +343,25 @@ fn has_fn(imp: &ast::Impl, rhs_name: &str) -> bool {
 
 /// Find the start of the `impl` block for the given `ast::Impl`.
 //
-// FIXME: add a way to find the end of the `impl` block.
 // FIXME: this partially overlaps with `find_struct_impl`
-pub(crate) fn find_impl_block(impl_def: ast::Impl, buf: &mut String) -> Option<TextSize> {
+pub(crate) fn find_impl_block_start(impl_def: ast::Impl, buf: &mut String) -> Option<TextSize> {
     buf.push('\n');
-    let start = impl_def
-        .syntax()
-        .descendants_with_tokens()
-        .find(|t| t.kind() == T!['{'])?
+    let start = impl_def.assoc_item_list().and_then(|it| it.l_curly_token())?.text_range().end();
+    Some(start)
+}
+
+/// Find the end of the `impl` block for the given `ast::Impl`.
+//
+// FIXME: this partially overlaps with `find_struct_impl`
+pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Option<TextSize> {
+    buf.push('\n');
+    let end = impl_def
+        .assoc_item_list()
+        .and_then(|it| it.r_curly_token())?
+        .prev_sibling_or_token()?
         .text_range()
         .end();
-    Some(start)
+    Some(end)
 }
 
 // Generates the surrounding `impl Type { <code> }` including type and lifetime