diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs index 500d52c2a2..1e20c0f48b 100644 --- a/crates/libeditor/src/code_actions.rs +++ b/crates/libeditor/src/code_actions.rs @@ -1,6 +1,6 @@ use {TextUnit, EditBuilder, Edit}; use libsyntax2::{ - ast::{self, AstNode, AttrsOwner, ParsedFile}, + ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner, ParsedFile}, SyntaxKind::COMMA, SyntaxNodeRef, algo::{ @@ -58,6 +58,36 @@ pub fn add_derive<'a>(file: &'a ParsedFile, offset: TextUnit) -> Option(file: &'a ParsedFile, offset: TextUnit) -> Option ActionResult + 'a> { + let nominal = find_node::(file.syntax(), offset)?; + let name = nominal.name()?; + + Some(move || { + // let type_params = nominal.type_param_list(); + // let type_args = match type_params { + // None => String::new(), + // Some(params) => { + // let mut buf = String::new(); + // } + // }; + let mut edit = EditBuilder::new(); + let start_offset = nominal.syntax().range().end(); + edit.insert( + start_offset, + format!( + "\n\nimpl {} {{\n\n}}", + name.text(), + ) + ); + ActionResult { + edit: edit.finish(), + cursor_position: Some( + start_offset + TextUnit::of_str("\n\nimpl {\n") + name.syntax().range().len() + ), + } + }) +} + fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option { siblings(node, direction) .skip(1) diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 12d0a30dd1..6bae7a3fa1 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs @@ -22,7 +22,7 @@ pub use self::{ edit::{EditBuilder, Edit, AtomEdit}, code_actions::{ ActionResult, find_node, - flip_comma, add_derive, + flip_comma, add_derive, add_impl, }, }; diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs index 4f4b4b773c..3b0ec78eb3 100644 --- a/crates/libeditor/tests/test.rs +++ b/crates/libeditor/tests/test.rs @@ -7,7 +7,7 @@ use assert_eq_text::{assert_eq_dbg}; use libeditor::{ ParsedFile, TextUnit, TextRange, ActionResult, highlight, runnables, extend_selection, file_structure, - flip_comma, add_derive, matching_brace, + flip_comma, add_derive, add_impl, matching_brace, }; #[test] @@ -144,6 +144,20 @@ fn test_add_derive() { ); } +#[test] +fn test_add_impl() { + check_action( + "struct Foo {<|>}\n", + "struct Foo {}\n\nimpl Foo {\n<|>\n}\n", + |file, off| add_impl(file, off).map(|f| f()), + ); + // check_action( + // "struct Foo {<|>}", + // "struct Foo {}\nimpl Foo {\n<|>\n}", + // |file, off| add_impl(file, off).map(|f| f()), + // ); +} + #[test] fn test_matching_brace() { fn do_check(before: &str, after: &str) { diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 0f53e8f4a8..6df1d2311e 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs @@ -344,8 +344,9 @@ impl<'a> AstNode<'a> for NominalDef<'a> { } } -impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {} +impl<'a> ast::NameOwner<'a> for NominalDef<'a> {} impl<'a> ast::TypeParamsOwner<'a> for NominalDef<'a> {} +impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {} impl<'a> NominalDef<'a> {} // ParenType diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index 83b56c3492..e56496be10 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron @@ -299,7 +299,11 @@ Grammar( "NominalDef": ( enum: ["StructDef", "EnumDef"], - traits: [ "AttrsOwner", "TypeParamsOwner" ], + traits: [ + "NameOwner", + "TypeParamsOwner", + "AttrsOwner" + ], ), "Name": (),