aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/add_function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers/add_function.rs')
-rw-r--r--crates/ra_assists/src/handlers/add_function.rs44
1 files changed, 19 insertions, 25 deletions
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs
index 6c7456579..278079665 100644
--- a/crates/ra_assists/src/handlers/add_function.rs
+++ b/crates/ra_assists/src/handlers/add_function.rs
@@ -3,9 +3,10 @@ use ra_syntax::{
3 SyntaxKind, SyntaxNode, TextSize, 3 SyntaxKind, SyntaxNode, TextSize,
4}; 4};
5 5
6use crate::{Assist, AssistCtx, AssistFile, AssistId}; 6use crate::{Assist, AssistCtx, AssistId};
7use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner}; 7use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner};
8use hir::HirDisplay; 8use hir::HirDisplay;
9use ra_db::FileId;
9use rustc_hash::{FxHashMap, FxHashSet}; 10use rustc_hash::{FxHashMap, FxHashSet};
10 11
11// Assist: add_function 12// Assist: add_function
@@ -57,14 +58,12 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> {
57 58
58 let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; 59 let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?;
59 60
60 ctx.add_assist(AssistId("add_function"), "Add function", |edit| { 61 let target = call.syntax().text_range();
61 edit.target(call.syntax().text_range()); 62 ctx.add_assist(AssistId("add_function"), "Add function", target, |edit| {
62 63 let function_template = function_builder.render();
63 if let Some(function_template) = function_builder.render() { 64 edit.set_file(function_template.file);
64 edit.set_file(function_template.file); 65 edit.set_cursor(function_template.cursor_offset);
65 edit.set_cursor(function_template.cursor_offset); 66 edit.insert(function_template.insert_offset, function_template.fn_def.to_string());
66 edit.insert(function_template.insert_offset, function_template.fn_def.to_string());
67 }
68 }) 67 })
69} 68}
70 69
@@ -72,7 +71,7 @@ struct FunctionTemplate {
72 insert_offset: TextSize, 71 insert_offset: TextSize,
73 cursor_offset: TextSize, 72 cursor_offset: TextSize,
74 fn_def: ast::SourceFile, 73 fn_def: ast::SourceFile,
75 file: AssistFile, 74 file: FileId,
76} 75}
77 76
78struct FunctionBuilder { 77struct FunctionBuilder {
@@ -80,7 +79,7 @@ struct FunctionBuilder {
80 fn_name: ast::Name, 79 fn_name: ast::Name,
81 type_params: Option<ast::TypeParamList>, 80 type_params: Option<ast::TypeParamList>,
82 params: ast::ParamList, 81 params: ast::ParamList,
83 file: AssistFile, 82 file: FileId,
84 needs_pub: bool, 83 needs_pub: bool,
85} 84}
86 85
@@ -94,7 +93,7 @@ impl FunctionBuilder {
94 target_module: Option<hir::InFile<hir::ModuleSource>>, 93 target_module: Option<hir::InFile<hir::ModuleSource>>,
95 ) -> Option<Self> { 94 ) -> Option<Self> {
96 let needs_pub = target_module.is_some(); 95 let needs_pub = target_module.is_some();
97 let mut file = AssistFile::default(); 96 let mut file = ctx.frange.file_id;
98 let target = if let Some(target_module) = target_module { 97 let target = if let Some(target_module) = target_module {
99 let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?; 98 let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?;
100 file = in_file; 99 file = in_file;
@@ -107,7 +106,7 @@ impl FunctionBuilder {
107 Some(Self { target, fn_name, type_params, params, file, needs_pub }) 106 Some(Self { target, fn_name, type_params, params, file, needs_pub })
108 } 107 }
109 108
110 fn render(self) -> Option<FunctionTemplate> { 109 fn render(self) -> FunctionTemplate {
111 let placeholder_expr = ast::make::expr_todo(); 110 let placeholder_expr = ast::make::expr_todo();
112 let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); 111 let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr));
113 let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); 112 let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body);
@@ -133,15 +132,11 @@ impl FunctionBuilder {
133 } 132 }
134 }; 133 };
135 134
136 let cursor_offset_from_fn_start = fn_def 135 let placeholder_expr =
137 .syntax() 136 fn_def.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
138 .descendants() 137 let cursor_offset_from_fn_start = placeholder_expr.syntax().text_range().start();
139 .find_map(ast::MacroCall::cast)?
140 .syntax()
141 .text_range()
142 .start();
143 let cursor_offset = insert_offset + cursor_offset_from_fn_start; 138 let cursor_offset = insert_offset + cursor_offset_from_fn_start;
144 Some(FunctionTemplate { insert_offset, cursor_offset, fn_def, file: self.file }) 139 FunctionTemplate { insert_offset, cursor_offset, fn_def, file: self.file }
145 } 140 }
146} 141}
147 142
@@ -259,9 +254,8 @@ fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFu
259fn next_space_for_fn_in_module( 254fn next_space_for_fn_in_module(
260 db: &dyn hir::db::AstDatabase, 255 db: &dyn hir::db::AstDatabase,
261 module: hir::InFile<hir::ModuleSource>, 256 module: hir::InFile<hir::ModuleSource>,
262) -> Option<(AssistFile, GeneratedFunctionTarget)> { 257) -> Option<(FileId, GeneratedFunctionTarget)> {
263 let file = module.file_id.original_file(db); 258 let file = module.file_id.original_file(db);
264 let assist_file = AssistFile::TargetFile(file);
265 let assist_item = match module.value { 259 let assist_item = match module.value {
266 hir::ModuleSource::SourceFile(it) => { 260 hir::ModuleSource::SourceFile(it) => {
267 if let Some(last_item) = it.items().last() { 261 if let Some(last_item) = it.items().last() {
@@ -278,12 +272,12 @@ fn next_space_for_fn_in_module(
278 } 272 }
279 } 273 }
280 }; 274 };
281 Some((assist_file, assist_item)) 275 Some((file, assist_item))
282} 276}
283 277
284#[cfg(test)] 278#[cfg(test)]
285mod tests { 279mod tests {
286 use crate::helpers::{check_assist, check_assist_not_applicable}; 280 use crate::tests::{check_assist, check_assist_not_applicable};
287 281
288 use super::*; 282 use super::*;
289 283