aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assist_context.rs17
-rw-r--r--crates/ra_assists/src/handlers/change_return_type_to_result.rs73
-rw-r--r--crates/ra_fmt/src/lib.rs5
-rw-r--r--crates/syntax/src/ast/make.rs7
4 files changed, 48 insertions, 54 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 217f692a4..368d48a71 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -5,14 +5,13 @@ use std::mem;
5use algo::find_covering_element; 5use algo::find_covering_element;
6use hir::Semantics; 6use hir::Semantics;
7use ra_db::{FileId, FileRange}; 7use ra_db::{FileId, FileRange};
8use ra_fmt::{leading_indent, reindent};
9use ra_ide_db::{ 8use ra_ide_db::{
10 source_change::{SourceChange, SourceFileEdit}, 9 source_change::{SourceChange, SourceFileEdit},
11 RootDatabase, 10 RootDatabase,
12}; 11};
13use syntax::{ 12use syntax::{
14 algo::{self, find_node_at_offset, SyntaxRewriter}, 13 algo::{self, find_node_at_offset, SyntaxRewriter},
15 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, 14 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxToken, TextRange, TextSize,
16 TokenAtOffset, 15 TokenAtOffset,
17}; 16};
18use text_edit::{TextEdit, TextEditBuilder}; 17use text_edit::{TextEdit, TextEditBuilder};
@@ -269,20 +268,6 @@ impl AssistBuilder {
269 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { 268 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
270 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) 269 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
271 } 270 }
272 /// Replaces specified `node` of text with a given string, reindenting the
273 /// string to maintain `node`'s existing indent.
274 // FIXME: remove in favor of syntax::edit::IndentLevel::increase_indent
275 pub(crate) fn replace_node_and_indent(
276 &mut self,
277 node: &SyntaxNode,
278 replace_with: impl Into<String>,
279 ) {
280 let mut replace_with = replace_with.into();
281 if let Some(indent) = leading_indent(node) {
282 replace_with = reindent(&replace_with, &indent)
283 }
284 self.replace(node.text_range(), replace_with)
285 }
286 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { 271 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) {
287 let node = rewriter.rewrite_root().unwrap(); 272 let node = rewriter.rewrite_root().unwrap();
288 let new = rewriter.rewrite(&node); 273 let new = rewriter.rewrite(&node);
diff --git a/crates/ra_assists/src/handlers/change_return_type_to_result.rs b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
index d5a68a24c..be480943c 100644
--- a/crates/ra_assists/src/handlers/change_return_type_to_result.rs
+++ b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
@@ -1,10 +1,12 @@
1use std::iter;
2
1use syntax::{ 3use syntax::{
2 ast::{self, BlockExpr, Expr, LoopBodyOwner}, 4 ast::{self, make, BlockExpr, Expr, LoopBodyOwner},
3 AstNode, SyntaxNode, 5 AstNode, SyntaxNode,
4}; 6};
7use test_utils::mark;
5 8
6use crate::{AssistContext, AssistId, AssistKind, Assists}; 9use crate::{AssistContext, AssistId, AssistKind, Assists};
7use test_utils::mark;
8 10
9// Assist: change_return_type_to_result 11// Assist: change_return_type_to_result
10// 12//
@@ -44,7 +46,13 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex
44 tail_return_expr_collector.collect_tail_exprs(block_expr); 46 tail_return_expr_collector.collect_tail_exprs(block_expr);
45 47
46 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap { 48 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
47 builder.replace_node_and_indent(&ret_expr_arg, format!("Ok({})", ret_expr_arg)); 49 let ok_wrapped = make::expr_call(
50 make::expr_path(make::path_unqualified(make::path_segment(make::name_ref(
51 "Ok",
52 )))),
53 make::arg_list(iter::once(ret_expr_arg.clone())),
54 );
55 builder.replace_ast(ret_expr_arg, ok_wrapped);
48 } 56 }
49 57
50 match ctx.config.snippet_cap { 58 match ctx.config.snippet_cap {
@@ -60,7 +68,7 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex
60} 68}
61 69
62struct TailReturnCollector { 70struct TailReturnCollector {
63 exprs_to_wrap: Vec<SyntaxNode>, 71 exprs_to_wrap: Vec<ast::Expr>,
64} 72}
65 73
66impl TailReturnCollector { 74impl TailReturnCollector {
@@ -86,7 +94,8 @@ impl TailReturnCollector {
86 if let Some(last_exprs) = get_tail_expr_from_block(&expr) { 94 if let Some(last_exprs) = get_tail_expr_from_block(&expr) {
87 for last_expr in last_exprs { 95 for last_expr in last_exprs {
88 let last_expr = match last_expr { 96 let last_expr = match last_expr {
89 NodeType::Node(expr) | NodeType::Leaf(expr) => expr, 97 NodeType::Node(expr) => expr,
98 NodeType::Leaf(expr) => expr.syntax().clone(),
90 }; 99 };
91 100
92 if let Some(last_expr) = Expr::cast(last_expr.clone()) { 101 if let Some(last_expr) = Expr::cast(last_expr.clone()) {
@@ -113,12 +122,12 @@ impl TailReturnCollector {
113 } 122 }
114 Expr::ReturnExpr(ret_expr) => { 123 Expr::ReturnExpr(ret_expr) => {
115 if let Some(ret_expr_arg) = &ret_expr.expr() { 124 if let Some(ret_expr_arg) = &ret_expr.expr() {
116 self.exprs_to_wrap.push(ret_expr_arg.syntax().clone()); 125 self.exprs_to_wrap.push(ret_expr_arg.clone());
117 } 126 }
118 } 127 }
119 Expr::BreakExpr(break_expr) if collect_break => { 128 Expr::BreakExpr(break_expr) if collect_break => {
120 if let Some(break_expr_arg) = &break_expr.expr() { 129 if let Some(break_expr_arg) = &break_expr.expr() {
121 self.exprs_to_wrap.push(break_expr_arg.syntax().clone()); 130 self.exprs_to_wrap.push(break_expr_arg.clone());
122 } 131 }
123 } 132 }
124 Expr::IfExpr(if_expr) => { 133 Expr::IfExpr(if_expr) => {
@@ -166,14 +175,11 @@ impl TailReturnCollector {
166 NodeType::Leaf(expr) => { 175 NodeType::Leaf(expr) => {
167 self.exprs_to_wrap.push(expr.clone()); 176 self.exprs_to_wrap.push(expr.clone());
168 } 177 }
169 NodeType::Node(expr) => match &Expr::cast(expr.clone()) { 178 NodeType::Node(expr) => {
170 Some(last_expr) => { 179 if let Some(last_expr) = Expr::cast(expr.clone()) {
171 self.fetch_tail_exprs(last_expr); 180 self.fetch_tail_exprs(&last_expr);
172 }
173 None => {
174 self.exprs_to_wrap.push(expr.clone());
175 } 181 }
176 }, 182 }
177 } 183 }
178 } 184 }
179 } 185 }
@@ -182,7 +188,7 @@ impl TailReturnCollector {
182 188
183#[derive(Debug)] 189#[derive(Debug)]
184enum NodeType { 190enum NodeType {
185 Leaf(SyntaxNode), 191 Leaf(ast::Expr),
186 Node(SyntaxNode), 192 Node(SyntaxNode),
187} 193}
188 194
@@ -233,25 +239,26 @@ fn get_tail_expr_from_block(expr: &Expr) -> Option<Vec<NodeType>> {
233 239
234 Some(arms) 240 Some(arms)
235 } 241 }
236 Expr::BreakExpr(expr) => expr.expr().map(|e| vec![NodeType::Leaf(e.syntax().clone())]), 242 Expr::BreakExpr(expr) => expr.expr().map(|e| vec![NodeType::Leaf(e)]),
237 Expr::ReturnExpr(ret_expr) => Some(vec![NodeType::Node(ret_expr.syntax().clone())]), 243 Expr::ReturnExpr(ret_expr) => Some(vec![NodeType::Node(ret_expr.syntax().clone())]),
238 Expr::CallExpr(call_expr) => Some(vec![NodeType::Leaf(call_expr.syntax().clone())]), 244
239 Expr::Literal(lit_expr) => Some(vec![NodeType::Leaf(lit_expr.syntax().clone())]), 245 Expr::CallExpr(_)
240 Expr::TupleExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 246 | Expr::Literal(_)
241 Expr::ArrayExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 247 | Expr::TupleExpr(_)
242 Expr::ParenExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 248 | Expr::ArrayExpr(_)
243 Expr::PathExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 249 | Expr::ParenExpr(_)
244 Expr::RecordExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 250 | Expr::PathExpr(_)
245 Expr::IndexExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 251 | Expr::RecordExpr(_)
246 Expr::MethodCallExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 252 | Expr::IndexExpr(_)
247 Expr::AwaitExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 253 | Expr::MethodCallExpr(_)
248 Expr::CastExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 254 | Expr::AwaitExpr(_)
249 Expr::RefExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 255 | Expr::CastExpr(_)
250 Expr::PrefixExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 256 | Expr::RefExpr(_)
251 Expr::RangeExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 257 | Expr::PrefixExpr(_)
252 Expr::BinExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 258 | Expr::RangeExpr(_)
253 Expr::MacroCall(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 259 | Expr::BinExpr(_)
254 Expr::BoxExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]), 260 | Expr::MacroCall(_)
261 | Expr::BoxExpr(_) => Some(vec![NodeType::Leaf(expr.clone())]),
255 _ => None, 262 _ => None,
256 } 263 }
257} 264}
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index d0bf0593f..397a3c3ae 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -10,11 +10,6 @@ use syntax::{
10 SyntaxNode, SyntaxToken, T, 10 SyntaxNode, SyntaxToken, T,
11}; 11};
12 12
13pub fn reindent(text: &str, indent: &str) -> String {
14 let indent = format!("\n{}", indent);
15 text.lines().intersperse(&indent).collect()
16}
17
18/// If the node is on the beginning of the line, calculate indent. 13/// If the node is on the beginning of the line, calculate indent.
19pub fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> { 14pub fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> {
20 for token in prev_tokens(node.first_token()?) { 15 for token in prev_tokens(node.first_token()?) {
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 3009faed7..d20c085aa 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -134,6 +134,9 @@ pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
134 let token = token(op); 134 let token = token(op);
135 expr_from_text(&format!("{}{}", token, expr)) 135 expr_from_text(&format!("{}{}", token, expr))
136} 136}
137pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
138 expr_from_text(&format!("{}{}", f, arg_list))
139}
137fn expr_from_text(text: &str) -> ast::Expr { 140fn expr_from_text(text: &str) -> ast::Expr {
138 ast_from_text(&format!("const C: () = {};", text)) 141 ast_from_text(&format!("const C: () = {};", text))
139} 142}
@@ -151,6 +154,10 @@ pub fn condition(expr: ast::Expr, pattern: Option<ast::Pat>) -> ast::Condition {
151 } 154 }
152} 155}
153 156
157pub fn arg_list(args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList {
158 ast_from_text(&format!("fn main() {{ ()({}) }}", args.into_iter().format(", ")))
159}
160
154pub fn ident_pat(name: ast::Name) -> ast::IdentPat { 161pub fn ident_pat(name: ast::Name) -> ast::IdentPat {
155 return from_text(name.text()); 162 return from_text(name.text());
156 163