mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Add a "Add attribute" assist
This commit is contained in:
		
							parent
							
								
									7e95c14ea7
								
							
						
					
					
						commit
						cb135ae71b
					
				
							
								
								
									
										196
									
								
								crates/ide-assists/src/handlers/add_attribute.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								crates/ide-assists/src/handlers/add_attribute.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
				
			|||||||
 | 
					use ide_db::assists::{AssistId, AssistKind, GroupLabel};
 | 
				
			||||||
 | 
					use syntax::{
 | 
				
			||||||
 | 
					    ast::{self, HasAttrs},
 | 
				
			||||||
 | 
					    match_ast, AstNode, SyntaxKind, TextSize,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::assist_context::{AssistContext, Assists};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Assist: add_attribute
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Adds commonly used attributes to items.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// struct Point {
 | 
				
			||||||
 | 
					//     x: u32,
 | 
				
			||||||
 | 
					//     y: u32,$0
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// ->add_derive
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// #[derive($0)]
 | 
				
			||||||
 | 
					// struct Point {
 | 
				
			||||||
 | 
					//     x: u32,
 | 
				
			||||||
 | 
					//     y: u32,
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					pub(crate) fn add_attribute(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
 | 
				
			||||||
 | 
					    let cap = ctx.config.snippet_cap?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let (attr_owner, attrs) = ctx
 | 
				
			||||||
 | 
					        .find_node_at_offset::<ast::AnyHasAttrs>()?
 | 
				
			||||||
 | 
					        .syntax()
 | 
				
			||||||
 | 
					        .ancestors()
 | 
				
			||||||
 | 
					        .filter_map(ast::AnyHasAttrs::cast)
 | 
				
			||||||
 | 
					        .find_map(|attr_owner| {
 | 
				
			||||||
 | 
					            let node = attr_owner.syntax();
 | 
				
			||||||
 | 
					            match_ast! {
 | 
				
			||||||
 | 
					                match node {
 | 
				
			||||||
 | 
					                    ast::Adt(_) => Some((attr_owner, ADT_ATTRS)),
 | 
				
			||||||
 | 
					                    ast::Fn(_) => Some((attr_owner, FN_ATTRS)),
 | 
				
			||||||
 | 
					                    _ => None,
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let offset = attr_insertion_offset(&attr_owner)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for tpl in attrs {
 | 
				
			||||||
 | 
					        let existing_offset = attr_owner.attrs().find_map(|attr| {
 | 
				
			||||||
 | 
					            if attr.simple_name()? == tpl.name {
 | 
				
			||||||
 | 
					                match attr.token_tree() {
 | 
				
			||||||
 | 
					                    Some(tt) => {
 | 
				
			||||||
 | 
					                        // Attribute like `#[derive(...)]`, position cursor right before the `)`
 | 
				
			||||||
 | 
					                        return Some(tt.syntax().text_range().end() - TextSize::of(')'));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    None => {
 | 
				
			||||||
 | 
					                        // `#[key = value]`
 | 
				
			||||||
 | 
					                        let tok = attr.syntax().last_token()?;
 | 
				
			||||||
 | 
					                        if tok.kind() == SyntaxKind::R_BRACK {
 | 
				
			||||||
 | 
					                            return Some(tok.text_range().end() - TextSize::of(']'));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        acc.add_group(
 | 
				
			||||||
 | 
					            &GroupLabel("Add attribute".into()),
 | 
				
			||||||
 | 
					            AssistId(tpl.id, AssistKind::Generate),
 | 
				
			||||||
 | 
					            format!("Add `#[{}]`", tpl.name),
 | 
				
			||||||
 | 
					            attr_owner.syntax().text_range(),
 | 
				
			||||||
 | 
					            |b| match existing_offset {
 | 
				
			||||||
 | 
					                Some(offset) => {
 | 
				
			||||||
 | 
					                    b.insert_snippet(cap, offset, "$0");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                None => {
 | 
				
			||||||
 | 
					                    b.insert_snippet(cap, offset, format!("#[{}]\n", tpl.snippet));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Some(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn attr_insertion_offset(nominal: &ast::AnyHasAttrs) -> Option<TextSize> {
 | 
				
			||||||
 | 
					    let non_ws_child = nominal
 | 
				
			||||||
 | 
					        .syntax()
 | 
				
			||||||
 | 
					        .children_with_tokens()
 | 
				
			||||||
 | 
					        .find(|it| it.kind() != SyntaxKind::COMMENT && it.kind() != SyntaxKind::WHITESPACE)?;
 | 
				
			||||||
 | 
					    Some(non_ws_child.text_range().start())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ADT_ATTRS: &[AttrTemplate] = &[
 | 
				
			||||||
 | 
					    AttrTemplate { id: "add_derive", name: "derive", snippet: "derive($0)" },
 | 
				
			||||||
 | 
					    AttrTemplate { id: "add_must_use", name: "must_use", snippet: "must_use$0" },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static FN_ATTRS: &[AttrTemplate] = &[
 | 
				
			||||||
 | 
					    AttrTemplate { id: "add_inline", name: "inline", snippet: "inline$0" },
 | 
				
			||||||
 | 
					    AttrTemplate { id: "add_must_use", name: "must_use", snippet: "must_use$0" },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct AttrTemplate {
 | 
				
			||||||
 | 
					    /// Assist ID.
 | 
				
			||||||
 | 
					    id: &'static str,
 | 
				
			||||||
 | 
					    /// User-facing attribute name.
 | 
				
			||||||
 | 
					    name: &'static str,
 | 
				
			||||||
 | 
					    /// Snippet to insert.
 | 
				
			||||||
 | 
					    snippet: &'static str,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use crate::tests::{check_assist_by_label, check_assist_target};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use super::add_attribute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn check_derive(ra_fixture_before: &str, ra_fixture_after: &str) {
 | 
				
			||||||
 | 
					        check_assist_by_label(
 | 
				
			||||||
 | 
					            add_attribute,
 | 
				
			||||||
 | 
					            ra_fixture_before,
 | 
				
			||||||
 | 
					            ra_fixture_after,
 | 
				
			||||||
 | 
					            "Add `#[derive]`",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn check_must_use(ra_fixture_before: &str, ra_fixture_after: &str) {
 | 
				
			||||||
 | 
					        check_assist_by_label(
 | 
				
			||||||
 | 
					            add_attribute,
 | 
				
			||||||
 | 
					            ra_fixture_before,
 | 
				
			||||||
 | 
					            ra_fixture_after,
 | 
				
			||||||
 | 
					            "Add `#[must_use]`",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn add_derive_new() {
 | 
				
			||||||
 | 
					        check_derive("struct Foo { a: i32, $0}", "#[derive($0)]\nstruct Foo { a: i32, }");
 | 
				
			||||||
 | 
					        check_derive("struct Foo { $0 a: i32, }", "#[derive($0)]\nstruct Foo {  a: i32, }");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn add_derive_existing() {
 | 
				
			||||||
 | 
					        check_derive(
 | 
				
			||||||
 | 
					            "#[derive(Clone)]\nstruct Foo { a: i32$0, }",
 | 
				
			||||||
 | 
					            "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn add_derive_new_with_doc_comment() {
 | 
				
			||||||
 | 
					        check_derive(
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					/// `Foo` is a pretty important struct.
 | 
				
			||||||
 | 
					/// It does stuff.
 | 
				
			||||||
 | 
					struct Foo { a: i32$0, }
 | 
				
			||||||
 | 
					            ",
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					/// `Foo` is a pretty important struct.
 | 
				
			||||||
 | 
					/// It does stuff.
 | 
				
			||||||
 | 
					#[derive($0)]
 | 
				
			||||||
 | 
					struct Foo { a: i32, }
 | 
				
			||||||
 | 
					            ",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn add_derive_target() {
 | 
				
			||||||
 | 
					        check_assist_target(
 | 
				
			||||||
 | 
					            add_attribute,
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					struct SomeThingIrrelevant;
 | 
				
			||||||
 | 
					/// `Foo` is a pretty important struct.
 | 
				
			||||||
 | 
					/// It does stuff.
 | 
				
			||||||
 | 
					struct Foo { a: i32$0, }
 | 
				
			||||||
 | 
					struct EvenMoreIrrelevant;
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
 | 
					            "/// `Foo` is a pretty important struct.
 | 
				
			||||||
 | 
					/// It does stuff.
 | 
				
			||||||
 | 
					struct Foo { a: i32, }",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn insert_must_use() {
 | 
				
			||||||
 | 
					        check_must_use("struct S$0;", "#[must_use$0]\nstruct S;");
 | 
				
			||||||
 | 
					        check_must_use("$0fn f() {}", "#[must_use$0]\nfn f() {}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        check_must_use(r#"#[must_use = "bla"] struct S$0;"#, r#"#[must_use = "bla"$0] struct S;"#);
 | 
				
			||||||
 | 
					        check_must_use(r#"#[must_use = ] struct S$0;"#, r#"#[must_use = $0] struct S;"#);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        check_must_use(r#"#[must_use = "bla"] $0fn f() {}"#, r#"#[must_use = "bla"$0] fn f() {}"#);
 | 
				
			||||||
 | 
					        check_must_use(r#"#[must_use = ] $0fn f() {}"#, r#"#[must_use = $0] fn f() {}"#);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,132 +0,0 @@
 | 
				
			|||||||
use syntax::{
 | 
					 | 
				
			||||||
    ast::{self, AstNode, HasAttrs},
 | 
					 | 
				
			||||||
    SyntaxKind::{COMMENT, WHITESPACE},
 | 
					 | 
				
			||||||
    TextSize,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Assist: generate_derive
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Adds a new `#[derive()]` clause to a struct or enum.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// ```
 | 
					 | 
				
			||||||
// struct Point {
 | 
					 | 
				
			||||||
//     x: u32,
 | 
					 | 
				
			||||||
//     y: u32,$0
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
// ```
 | 
					 | 
				
			||||||
// ->
 | 
					 | 
				
			||||||
// ```
 | 
					 | 
				
			||||||
// #[derive($0)]
 | 
					 | 
				
			||||||
// struct Point {
 | 
					 | 
				
			||||||
//     x: u32,
 | 
					 | 
				
			||||||
//     y: u32,
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
// ```
 | 
					 | 
				
			||||||
pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
 | 
					 | 
				
			||||||
    let cap = ctx.config.snippet_cap?;
 | 
					 | 
				
			||||||
    let nominal = ctx.find_node_at_offset::<ast::Adt>()?;
 | 
					 | 
				
			||||||
    let node_start = derive_insertion_offset(&nominal)?;
 | 
					 | 
				
			||||||
    let target = nominal.syntax().text_range();
 | 
					 | 
				
			||||||
    acc.add(
 | 
					 | 
				
			||||||
        AssistId("generate_derive", AssistKind::Generate),
 | 
					 | 
				
			||||||
        "Add `#[derive]`",
 | 
					 | 
				
			||||||
        target,
 | 
					 | 
				
			||||||
        |builder| {
 | 
					 | 
				
			||||||
            let derive_attr = nominal
 | 
					 | 
				
			||||||
                .attrs()
 | 
					 | 
				
			||||||
                .filter_map(|x| x.as_simple_call())
 | 
					 | 
				
			||||||
                .filter(|(name, _arg)| name == "derive")
 | 
					 | 
				
			||||||
                .map(|(_name, arg)| arg)
 | 
					 | 
				
			||||||
                .next();
 | 
					 | 
				
			||||||
            match derive_attr {
 | 
					 | 
				
			||||||
                None => {
 | 
					 | 
				
			||||||
                    builder.insert_snippet(cap, node_start, "#[derive($0)]\n");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                Some(tt) => {
 | 
					 | 
				
			||||||
                    // Just move the cursor.
 | 
					 | 
				
			||||||
                    builder.insert_snippet(
 | 
					 | 
				
			||||||
                        cap,
 | 
					 | 
				
			||||||
                        tt.syntax().text_range().end() - TextSize::of(')'),
 | 
					 | 
				
			||||||
                        "$0",
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Insert `derive` after doc comments.
 | 
					 | 
				
			||||||
fn derive_insertion_offset(nominal: &ast::Adt) -> Option<TextSize> {
 | 
					 | 
				
			||||||
    let non_ws_child = nominal
 | 
					 | 
				
			||||||
        .syntax()
 | 
					 | 
				
			||||||
        .children_with_tokens()
 | 
					 | 
				
			||||||
        .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
 | 
					 | 
				
			||||||
    Some(non_ws_child.text_range().start())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(test)]
 | 
					 | 
				
			||||||
mod tests {
 | 
					 | 
				
			||||||
    use crate::tests::{check_assist, check_assist_target};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    use super::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn add_derive_new() {
 | 
					 | 
				
			||||||
        check_assist(
 | 
					 | 
				
			||||||
            generate_derive,
 | 
					 | 
				
			||||||
            "struct Foo { a: i32, $0}",
 | 
					 | 
				
			||||||
            "#[derive($0)]\nstruct Foo { a: i32, }",
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        check_assist(
 | 
					 | 
				
			||||||
            generate_derive,
 | 
					 | 
				
			||||||
            "struct Foo { $0 a: i32, }",
 | 
					 | 
				
			||||||
            "#[derive($0)]\nstruct Foo {  a: i32, }",
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn add_derive_existing() {
 | 
					 | 
				
			||||||
        check_assist(
 | 
					 | 
				
			||||||
            generate_derive,
 | 
					 | 
				
			||||||
            "#[derive(Clone)]\nstruct Foo { a: i32$0, }",
 | 
					 | 
				
			||||||
            "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn add_derive_new_with_doc_comment() {
 | 
					 | 
				
			||||||
        check_assist(
 | 
					 | 
				
			||||||
            generate_derive,
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
/// `Foo` is a pretty important struct.
 | 
					 | 
				
			||||||
/// It does stuff.
 | 
					 | 
				
			||||||
struct Foo { a: i32$0, }
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
/// `Foo` is a pretty important struct.
 | 
					 | 
				
			||||||
/// It does stuff.
 | 
					 | 
				
			||||||
#[derive($0)]
 | 
					 | 
				
			||||||
struct Foo { a: i32, }
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[test]
 | 
					 | 
				
			||||||
    fn add_derive_target() {
 | 
					 | 
				
			||||||
        check_assist_target(
 | 
					 | 
				
			||||||
            generate_derive,
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
struct SomeThingIrrelevant;
 | 
					 | 
				
			||||||
/// `Foo` is a pretty important struct.
 | 
					 | 
				
			||||||
/// It does stuff.
 | 
					 | 
				
			||||||
struct Foo { a: i32$0, }
 | 
					 | 
				
			||||||
struct EvenMoreIrrelevant;
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
            "/// `Foo` is a pretty important struct.
 | 
					 | 
				
			||||||
/// It does stuff.
 | 
					 | 
				
			||||||
struct Foo { a: i32, }",
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -38,7 +38,6 @@ use crate::{
 | 
				
			|||||||
// }
 | 
					// }
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// impl Person {
 | 
					// impl Person {
 | 
				
			||||||
//     #[must_use]
 | 
					 | 
				
			||||||
//     fn $0name(&self) -> &str {
 | 
					//     fn $0name(&self) -> &str {
 | 
				
			||||||
//         self.name.as_ref()
 | 
					//         self.name.as_ref()
 | 
				
			||||||
//     }
 | 
					//     }
 | 
				
			||||||
@ -64,7 +63,6 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<
 | 
				
			|||||||
// }
 | 
					// }
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// impl Person {
 | 
					// impl Person {
 | 
				
			||||||
//     #[must_use]
 | 
					 | 
				
			||||||
//     fn $0name_mut(&mut self) -> &mut String {
 | 
					//     fn $0name_mut(&mut self) -> &mut String {
 | 
				
			||||||
//         &mut self.name
 | 
					//         &mut self.name
 | 
				
			||||||
//     }
 | 
					//     }
 | 
				
			||||||
@ -133,8 +131,7 @@ pub(crate) fn generate_getter_impl(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            format_to!(
 | 
					            format_to!(
 | 
				
			||||||
                buf,
 | 
					                buf,
 | 
				
			||||||
                "    #[must_use]
 | 
					                "    {}fn {}(&{}self) -> {} {{
 | 
				
			||||||
    {}fn {}(&{}self) -> {} {{
 | 
					 | 
				
			||||||
        {}
 | 
					        {}
 | 
				
			||||||
    }}",
 | 
					    }}",
 | 
				
			||||||
                vis,
 | 
					                vis,
 | 
				
			||||||
@ -182,7 +179,6 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0data(&self) -> &Data {
 | 
					    fn $0data(&self) -> &Data {
 | 
				
			||||||
        &self.data
 | 
					        &self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -203,7 +199,6 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0data_mut(&mut self) -> &mut Data {
 | 
					    fn $0data_mut(&mut self) -> &mut Data {
 | 
				
			||||||
        &mut self.data
 | 
					        &mut self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -237,7 +232,6 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn data_mut(&mut self) -> &mut Data {
 | 
					    fn data_mut(&mut self) -> &mut Data {
 | 
				
			||||||
        &mut self.data
 | 
					        &mut self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -261,7 +255,6 @@ pub(crate) struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    pub(crate) fn $0data(&self) -> &Data {
 | 
					    pub(crate) fn $0data(&self) -> &Data {
 | 
				
			||||||
        &self.data
 | 
					        &self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -281,7 +274,6 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn data(&self) -> &Data {
 | 
					    fn data(&self) -> &Data {
 | 
				
			||||||
        &self.data
 | 
					        &self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -294,12 +286,10 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn data(&self) -> &Data {
 | 
					    fn data(&self) -> &Data {
 | 
				
			||||||
        &self.data
 | 
					        &self.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0count(&self) -> &usize {
 | 
					    fn $0count(&self) -> &usize {
 | 
				
			||||||
        &self.count
 | 
					        &self.count
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -325,7 +315,6 @@ pub struct String;
 | 
				
			|||||||
struct S { foo: String }
 | 
					struct S { foo: String }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> &String {
 | 
					    fn $0foo(&self) -> &String {
 | 
				
			||||||
        &self.foo
 | 
					        &self.foo
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -349,7 +338,6 @@ struct S { foo: $0bool }
 | 
				
			|||||||
struct S { foo: bool }
 | 
					struct S { foo: bool }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> bool {
 | 
					    fn $0foo(&self) -> bool {
 | 
				
			||||||
        self.foo
 | 
					        self.foo
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -382,7 +370,6 @@ impl AsRef<str> for String {
 | 
				
			|||||||
struct S { foo: String }
 | 
					struct S { foo: String }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> &str {
 | 
					    fn $0foo(&self) -> &str {
 | 
				
			||||||
        self.foo.as_ref()
 | 
					        self.foo.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -419,7 +406,6 @@ impl<T> AsRef<T> for Box<T> {
 | 
				
			|||||||
struct S { foo: Box<Sweets> }
 | 
					struct S { foo: Box<Sweets> }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> &Sweets {
 | 
					    fn $0foo(&self) -> &Sweets {
 | 
				
			||||||
        self.foo.as_ref()
 | 
					        self.foo.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -452,7 +438,6 @@ impl<T> AsRef<[T]> for Vec<T> {
 | 
				
			|||||||
struct S { foo: Vec<()> }
 | 
					struct S { foo: Vec<()> }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> &[()] {
 | 
					    fn $0foo(&self) -> &[()] {
 | 
				
			||||||
        self.foo.as_ref()
 | 
					        self.foo.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -475,7 +460,6 @@ struct Failure;
 | 
				
			|||||||
struct S { foo: Option<Failure> }
 | 
					struct S { foo: Option<Failure> }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl S {
 | 
					impl S {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0foo(&self) -> Option<&Failure> {
 | 
					    fn $0foo(&self) -> Option<&Failure> {
 | 
				
			||||||
        self.foo.as_ref()
 | 
					        self.foo.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -498,7 +482,6 @@ struct Context {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Context {
 | 
					impl Context {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0data(&self) -> Result<&bool, &i32> {
 | 
					    fn $0data(&self) -> Result<&bool, &i32> {
 | 
				
			||||||
        self.data.as_ref()
 | 
					        self.data.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -106,6 +106,8 @@ mod handlers {
 | 
				
			|||||||
    mod add_explicit_type;
 | 
					    mod add_explicit_type;
 | 
				
			||||||
    mod add_lifetime_to_type;
 | 
					    mod add_lifetime_to_type;
 | 
				
			||||||
    mod add_missing_impl_members;
 | 
					    mod add_missing_impl_members;
 | 
				
			||||||
 | 
					    mod add_missing_match_arms;
 | 
				
			||||||
 | 
					    mod add_attribute;
 | 
				
			||||||
    mod add_turbo_fish;
 | 
					    mod add_turbo_fish;
 | 
				
			||||||
    mod apply_demorgan;
 | 
					    mod apply_demorgan;
 | 
				
			||||||
    mod auto_import;
 | 
					    mod auto_import;
 | 
				
			||||||
@ -125,7 +127,6 @@ mod handlers {
 | 
				
			|||||||
    mod extract_struct_from_enum_variant;
 | 
					    mod extract_struct_from_enum_variant;
 | 
				
			||||||
    mod extract_type_alias;
 | 
					    mod extract_type_alias;
 | 
				
			||||||
    mod extract_variable;
 | 
					    mod extract_variable;
 | 
				
			||||||
    mod add_missing_match_arms;
 | 
					 | 
				
			||||||
    mod fix_visibility;
 | 
					    mod fix_visibility;
 | 
				
			||||||
    mod flip_binexpr;
 | 
					    mod flip_binexpr;
 | 
				
			||||||
    mod flip_comma;
 | 
					    mod flip_comma;
 | 
				
			||||||
@ -134,7 +135,6 @@ mod handlers {
 | 
				
			|||||||
    mod generate_default_from_enum_variant;
 | 
					    mod generate_default_from_enum_variant;
 | 
				
			||||||
    mod generate_default_from_new;
 | 
					    mod generate_default_from_new;
 | 
				
			||||||
    mod generate_deref;
 | 
					    mod generate_deref;
 | 
				
			||||||
    mod generate_derive;
 | 
					 | 
				
			||||||
    mod generate_documentation_template;
 | 
					    mod generate_documentation_template;
 | 
				
			||||||
    mod generate_enum_is_method;
 | 
					    mod generate_enum_is_method;
 | 
				
			||||||
    mod generate_enum_projection_method;
 | 
					    mod generate_enum_projection_method;
 | 
				
			||||||
@ -190,6 +190,7 @@ mod handlers {
 | 
				
			|||||||
    pub(crate) fn all() -> &'static [Handler] {
 | 
					    pub(crate) fn all() -> &'static [Handler] {
 | 
				
			||||||
        &[
 | 
					        &[
 | 
				
			||||||
            // These are alphabetic for the foolish consistency
 | 
					            // These are alphabetic for the foolish consistency
 | 
				
			||||||
 | 
					            add_attribute::add_attribute,
 | 
				
			||||||
            add_explicit_type::add_explicit_type,
 | 
					            add_explicit_type::add_explicit_type,
 | 
				
			||||||
            add_missing_match_arms::add_missing_match_arms,
 | 
					            add_missing_match_arms::add_missing_match_arms,
 | 
				
			||||||
            add_lifetime_to_type::add_lifetime_to_type,
 | 
					            add_lifetime_to_type::add_lifetime_to_type,
 | 
				
			||||||
@ -219,7 +220,6 @@ mod handlers {
 | 
				
			|||||||
            generate_constant::generate_constant,
 | 
					            generate_constant::generate_constant,
 | 
				
			||||||
            generate_default_from_enum_variant::generate_default_from_enum_variant,
 | 
					            generate_default_from_enum_variant::generate_default_from_enum_variant,
 | 
				
			||||||
            generate_default_from_new::generate_default_from_new,
 | 
					            generate_default_from_new::generate_default_from_new,
 | 
				
			||||||
            generate_derive::generate_derive,
 | 
					 | 
				
			||||||
            generate_documentation_template::generate_documentation_template,
 | 
					            generate_documentation_template::generate_documentation_template,
 | 
				
			||||||
            generate_enum_is_method::generate_enum_is_method,
 | 
					            generate_enum_is_method::generate_enum_is_method,
 | 
				
			||||||
            generate_enum_projection_method::generate_enum_as_method,
 | 
					            generate_enum_projection_method::generate_enum_as_method,
 | 
				
			||||||
 | 
				
			|||||||
@ -251,6 +251,7 @@ pub fn test_some_range(a: int) -> bool {
 | 
				
			|||||||
        Extract into variable
 | 
					        Extract into variable
 | 
				
			||||||
        Extract into function
 | 
					        Extract into function
 | 
				
			||||||
        Replace if let with match
 | 
					        Replace if let with match
 | 
				
			||||||
 | 
					        Add attribute
 | 
				
			||||||
    "#]]
 | 
					    "#]]
 | 
				
			||||||
    .assert_eq(&expected);
 | 
					    .assert_eq(&expected);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use super::check_doc_test;
 | 
					use super::check_doc_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn doctest_add_attribute() {
 | 
				
			||||||
 | 
					    check_doc_test(
 | 
				
			||||||
 | 
					        "add_derive",
 | 
				
			||||||
 | 
					        r#####"
 | 
				
			||||||
 | 
					struct Point {
 | 
				
			||||||
 | 
					    x: u32,
 | 
				
			||||||
 | 
					    y: u32,$0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"#####,
 | 
				
			||||||
 | 
					        r#####"
 | 
				
			||||||
 | 
					#[derive($0)]
 | 
				
			||||||
 | 
					struct Point {
 | 
				
			||||||
 | 
					    x: u32,
 | 
				
			||||||
 | 
					    y: u32,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"#####,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn doctest_add_explicit_type() {
 | 
					fn doctest_add_explicit_type() {
 | 
				
			||||||
    check_doc_test(
 | 
					    check_doc_test(
 | 
				
			||||||
@ -822,26 +842,6 @@ impl core::ops::Deref for B {
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[test]
 | 
					 | 
				
			||||||
fn doctest_generate_derive() {
 | 
					 | 
				
			||||||
    check_doc_test(
 | 
					 | 
				
			||||||
        "generate_derive",
 | 
					 | 
				
			||||||
        r#####"
 | 
					 | 
				
			||||||
struct Point {
 | 
					 | 
				
			||||||
    x: u32,
 | 
					 | 
				
			||||||
    y: u32,$0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
"#####,
 | 
					 | 
				
			||||||
        r#####"
 | 
					 | 
				
			||||||
#[derive($0)]
 | 
					 | 
				
			||||||
struct Point {
 | 
					 | 
				
			||||||
    x: u32,
 | 
					 | 
				
			||||||
    y: u32,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
"#####,
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn doctest_generate_documentation_template() {
 | 
					fn doctest_generate_documentation_template() {
 | 
				
			||||||
    check_doc_test(
 | 
					    check_doc_test(
 | 
				
			||||||
@ -1037,7 +1037,6 @@ struct Person {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Person {
 | 
					impl Person {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0name(&self) -> &str {
 | 
					    fn $0name(&self) -> &str {
 | 
				
			||||||
        self.name.as_ref()
 | 
					        self.name.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1061,7 +1060,6 @@ struct Person {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Person {
 | 
					impl Person {
 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    fn $0name_mut(&mut self) -> &mut String {
 | 
					    fn $0name_mut(&mut self) -> &mut String {
 | 
				
			||||||
        &mut self.name
 | 
					        &mut self.name
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ r#####"
 | 
				
			|||||||
}}
 | 
					}}
 | 
				
			||||||
"######,
 | 
					"######,
 | 
				
			||||||
                    &test_id,
 | 
					                    &test_id,
 | 
				
			||||||
                    &assist.id,
 | 
					                    §ion.assist_id,
 | 
				
			||||||
                    reveal_hash_comments(§ion.before),
 | 
					                    reveal_hash_comments(§ion.before),
 | 
				
			||||||
                    reveal_hash_comments(§ion.after)
 | 
					                    reveal_hash_comments(§ion.after)
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
@ -61,6 +61,7 @@ r#####"
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct Section {
 | 
					struct Section {
 | 
				
			||||||
 | 
					    assist_id: String,
 | 
				
			||||||
    doc: String,
 | 
					    doc: String,
 | 
				
			||||||
    before: String,
 | 
					    before: String,
 | 
				
			||||||
    after: String,
 | 
					    after: String,
 | 
				
			||||||
@ -111,11 +112,13 @@ impl Assist {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    let before = take_until(lines.by_ref(), "```");
 | 
					                    let before = take_until(lines.by_ref(), "```");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    assert_eq!(lines.next().unwrap().as_str(), "->");
 | 
					                    let arrow = lines.next().unwrap();
 | 
				
			||||||
 | 
					                    assert!(arrow.starts_with("->"));
 | 
				
			||||||
 | 
					                    let id = if arrow[2..].is_empty() { &assist.id } else { &arrow[2..] };
 | 
				
			||||||
                    assert_eq!(lines.next().unwrap().as_str(), "```");
 | 
					                    assert_eq!(lines.next().unwrap().as_str(), "```");
 | 
				
			||||||
                    let after = take_until(lines.by_ref(), "```");
 | 
					                    let after = take_until(lines.by_ref(), "```");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    assist.sections.push(Section { doc, before, after });
 | 
					                    assist.sections.push(Section { assist_id: id.to_string(), doc, before, after });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                acc.push(assist)
 | 
					                acc.push(assist)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user