From f32081fa185b3a9df021f277c2c27fbd123d0951 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 14:29:41 +0300 Subject: move assists to subdir --- crates/ra_assists/src/assists/add_derive.rs | 105 ++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 crates/ra_assists/src/assists/add_derive.rs (limited to 'crates/ra_assists/src/assists/add_derive.rs') diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs new file mode 100644 index 000000000..9c88644df --- /dev/null +++ b/crates/ra_assists/src/assists/add_derive.rs @@ -0,0 +1,105 @@ +use hir::db::HirDatabase; +use ra_syntax::{ + ast::{self, AstNode, AttrsOwner}, + SyntaxKind::{COMMENT, WHITESPACE}, + TextUnit, +}; + +use crate::{Assist, AssistCtx, AssistId}; + +pub(crate) fn add_derive(mut ctx: AssistCtx) -> Option { + let nominal = ctx.node_at_offset::()?; + let node_start = derive_insertion_offset(&nominal)?; + ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { + let derive_attr = nominal + .attrs() + .filter_map(|x| x.as_call()) + .filter(|(name, _arg)| name == "derive") + .map(|(_name, arg)| arg) + .next(); + let offset = match derive_attr { + None => { + edit.insert(node_start, "#[derive()]\n"); + node_start + TextUnit::of_str("#[derive(") + } + Some(tt) => tt.syntax().text_range().end() - TextUnit::of_char(')'), + }; + edit.target(nominal.syntax().text_range()); + edit.set_cursor(offset) + }); + + ctx.build() +} + +// Insert `derive` after doc comments. +fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option { + 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 super::*; + use crate::helpers::{check_assist, check_assist_target}; + + #[test] + fn add_derive_new() { + check_assist( + add_derive, + "struct Foo { a: i32, <|>}", + "#[derive(<|>)]\nstruct Foo { a: i32, }", + ); + check_assist( + add_derive, + "struct Foo { <|> a: i32, }", + "#[derive(<|>)]\nstruct Foo { a: i32, }", + ); + } + + #[test] + fn add_derive_existing() { + check_assist( + add_derive, + "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", + "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", + ); + } + + #[test] + fn add_derive_new_with_doc_comment() { + check_assist( + add_derive, + " +/// `Foo` is a pretty important struct. +/// It does stuff. +struct Foo { a: i32<|>, } + ", + " +/// `Foo` is a pretty important struct. +/// It does stuff. +#[derive(<|>)] +struct Foo { a: i32, } + ", + ); + } + + #[test] + fn add_derive_target() { + check_assist_target( + add_derive, + " +struct SomeThingIrrelevant; +/// `Foo` is a pretty important struct. +/// It does stuff. +struct Foo { a: i32<|>, } +struct EvenMoreIrrelevant; + ", + "/// `Foo` is a pretty important struct. +/// It does stuff. +struct Foo { a: i32, }", + ); + } +} -- cgit v1.2.3