aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r--crates/libeditor/src/code_actions.rs68
1 files changed, 50 insertions, 18 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs
index 1e20c0f48..6c41923dd 100644
--- a/crates/libeditor/src/code_actions.rs
+++ b/crates/libeditor/src/code_actions.rs
@@ -1,4 +1,7 @@
1use {TextUnit, EditBuilder, Edit}; 1use std::{
2 fmt::{self, Write},
3};
4
2use libsyntax2::{ 5use libsyntax2::{
3 ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner, ParsedFile}, 6 ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner, ParsedFile},
4 SyntaxKind::COMMA, 7 SyntaxKind::COMMA,
@@ -9,6 +12,8 @@ use libsyntax2::{
9 }, 12 },
10}; 13};
11 14
15use {TextUnit, EditBuilder, Edit};
16
12pub struct ActionResult { 17pub struct ActionResult {
13 pub edit: Edit, 18 pub edit: Edit,
14 pub cursor_position: Option<TextUnit>, 19 pub cursor_position: Option<TextUnit>,
@@ -63,27 +68,31 @@ pub fn add_impl<'a>(file: &'a ParsedFile, offset: TextUnit) -> Option<impl FnOnc
63 let name = nominal.name()?; 68 let name = nominal.name()?;
64 69
65 Some(move || { 70 Some(move || {
66 // let type_params = nominal.type_param_list(); 71 let type_params = nominal.type_param_list();
67 // let type_args = match type_params {
68 // None => String::new(),
69 // Some(params) => {
70 // let mut buf = String::new();
71 // }
72 // };
73 let mut edit = EditBuilder::new(); 72 let mut edit = EditBuilder::new();
74 let start_offset = nominal.syntax().range().end(); 73 let start_offset = nominal.syntax().range().end();
75 edit.insert( 74 let mut buf = String::new();
76 start_offset, 75 buf.push_str("\n\nimpl");
77 format!( 76 if let Some(type_params) = type_params {
78 "\n\nimpl {} {{\n\n}}", 77 buf.push_display(&type_params.syntax().text());
79 name.text(), 78 }
80 ) 79 buf.push_str(" ");
81 ); 80 buf.push_str(name.text().as_str());
81 if let Some(type_params) = type_params {
82 comma_list(
83 &mut buf, "<", ">",
84 type_params.type_params()
85 .filter_map(|it| it.name())
86 .map(|it| it.text())
87 );
88 }
89 buf.push_str(" {\n");
90 let offset = start_offset + TextUnit::of_str(&buf);
91 buf.push_str("\n}");
92 edit.insert(start_offset, buf);
82 ActionResult { 93 ActionResult {
83 edit: edit.finish(), 94 edit: edit.finish(),
84 cursor_position: Some( 95 cursor_position: Some(offset),
85 start_offset + TextUnit::of_str("\n\nimpl {\n") + name.syntax().range().len()
86 ),
87 } 96 }
88 }) 97 })
89} 98}
@@ -104,3 +113,26 @@ pub fn find_node<'a, N: AstNode<'a>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit
104 .next() 113 .next()
105} 114}
106 115
116fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) {
117 buf.push_str(bra);
118 let mut first = true;
119 for item in items {
120 if !first {
121 first = false;
122 buf.push_str(", ");
123 }
124 write!(buf, "{}", item).unwrap();
125 }
126 buf.push_str(ket);
127}
128
129trait PushDisplay {
130 fn push_display<T: fmt::Display>(&mut self, item: &T);
131}
132
133impl PushDisplay for String {
134 fn push_display<T: fmt::Display>(&mut self, item: &T) {
135 use std::fmt::Write;
136 write!(self, "{}", item).unwrap()
137 }
138}