From edd3768a4411ab858332f36d634249534c65a0c5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 2 Dec 2018 12:19:22 +0300 Subject: Add `derive` after doc comments --- crates/ra_editor/src/code_actions.rs | 41 +++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 0139b19d3..37e963bbd 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs @@ -4,7 +4,7 @@ use ra_syntax::{ algo::{find_covering_node, find_leaf_at_offset}, ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, Direction, SourceFileNode, - SyntaxKind::{COMMA, WHITESPACE}, + SyntaxKind::{COMMA, WHITESPACE, COMMENT}, SyntaxNodeRef, TextRange, TextUnit, }; @@ -41,7 +41,8 @@ pub fn add_derive<'a>( offset: TextUnit, ) -> Option LocalEdit + 'a> { let nominal = find_node_at_offset::(file.syntax(), offset)?; - Some(move || { + let node_start = derive_insertion_offset(nominal)?; + return Some(move || { let derive_attr = nominal .attrs() .filter_map(|x| x.as_call()) @@ -51,7 +52,6 @@ pub fn add_derive<'a>( let mut edit = EditBuilder::new(); let offset = match derive_attr { None => { - let node_start = nominal.syntax().range().start(); edit.insert(node_start, "#[derive()]\n".to_string()); node_start + TextUnit::of_str("#[derive(") } @@ -61,7 +61,16 @@ pub fn add_derive<'a>( edit: edit.finish(), cursor_position: Some(offset), } - }) + }); + + // Insert `derive` after doc comments. + fn derive_insertion_offset(nominal: ast::NominalDef) -> Option { + let non_ws_child = nominal + .syntax() + .children() + .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?; + Some(non_ws_child.range().start()) + } } pub fn add_impl<'a>( @@ -181,7 +190,7 @@ mod tests { } #[test] - fn test_add_derive() { + fn add_derive_new() { check_action( "struct Foo { a: i32, <|>}", "#[derive(<|>)]\nstruct Foo { a: i32, }", @@ -192,6 +201,10 @@ mod tests { "#[derive(<|>)]\nstruct Foo { a: i32, }", |file, off| add_derive(file, off).map(|f| f()), ); + } + + #[test] + fn add_derive_existing() { check_action( "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", @@ -199,6 +212,24 @@ mod tests { ); } + #[test] + fn add_derive_new_with_doc_comment() { + check_action( + " +/// `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, } + ", + |file, off| add_derive(file, off).map(|f| f()), + ); + } + #[test] fn test_add_impl() { check_action( -- cgit v1.2.3