diff options
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r-- | crates/libeditor/src/code_actions.rs | 68 |
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 @@ | |||
1 | use {TextUnit, EditBuilder, Edit}; | 1 | use std::{ |
2 | fmt::{self, Write}, | ||
3 | }; | ||
4 | |||
2 | use libsyntax2::{ | 5 | use 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 | ||
15 | use {TextUnit, EditBuilder, Edit}; | ||
16 | |||
12 | pub struct ActionResult { | 17 | pub 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 | ||
116 | fn 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 | |||
129 | trait PushDisplay { | ||
130 | fn push_display<T: fmt::Display>(&mut self, item: &T); | ||
131 | } | ||
132 | |||
133 | impl 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 | } | ||