aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src')
-rw-r--r--crates/ra_assists/src/assist_ctx.rs8
-rw-r--r--crates/ra_assists/src/assists/add_derive.rs2
-rw-r--r--crates/ra_assists/src/assists/add_explicit_type.rs2
-rw-r--r--crates/ra_assists/src/assists/add_impl.rs2
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs2
-rw-r--r--crates/ra_assists/src/assists/apply_demorgan.rs2
-rw-r--r--crates/ra_assists/src/assists/auto_import.rs2
-rw-r--r--crates/ra_assists/src/assists/change_visibility.rs2
-rw-r--r--crates/ra_assists/src/assists/early_return.rs2
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs2
-rw-r--r--crates/ra_assists/src/assists/flip_binexpr.rs2
-rw-r--r--crates/ra_assists/src/assists/flip_comma.rs2
-rw-r--r--crates/ra_assists/src/assists/inline_local_variable.rs2
-rw-r--r--crates/ra_assists/src/assists/merge_match_arms.rs2
-rw-r--r--crates/ra_assists/src/assists/move_bounds.rs2
-rw-r--r--crates/ra_assists/src/assists/move_guard.rs4
-rw-r--r--crates/ra_assists/src/assists/raw_string.rs104
-rw-r--r--crates/ra_assists/src/assists/remove_dbg.rs2
-rw-r--r--crates/ra_assists/src/assists/replace_if_let_with_match.rs2
-rw-r--r--crates/ra_assists/src/assists/split_import.rs2
20 files changed, 78 insertions, 72 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index e270c5d60..5f85f20e2 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -5,7 +5,7 @@ use ra_db::FileRange;
5use ra_fmt::{leading_indent, reindent}; 5use ra_fmt::{leading_indent, reindent};
6use ra_syntax::{ 6use ra_syntax::{
7 algo::{self, find_covering_element, find_node_at_offset}, 7 algo::{self, find_covering_element, find_node_at_offset},
8 AstNode, SourceFile, SyntaxElement, SyntaxNode, SyntaxToken, TextRange, TextUnit, 8 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
9 TokenAtOffset, 9 TokenAtOffset,
10}; 10};
11use ra_text_edit::TextEditBuilder; 11use ra_text_edit::TextEditBuilder;
@@ -111,7 +111,11 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
111 self.source_file.syntax().token_at_offset(self.frange.range.start()) 111 self.source_file.syntax().token_at_offset(self.frange.range.start())
112 } 112 }
113 113
114 pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<N> { 114 pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
115 self.token_at_offset().find(|it| it.kind() == kind)
116 }
117
118 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
115 find_node_at_offset(self.source_file.syntax(), self.frange.range.start()) 119 find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
116 } 120 }
117 pub(crate) fn covering_element(&self) -> SyntaxElement { 121 pub(crate) fn covering_element(&self) -> SyntaxElement {
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs
index b077acb81..d1e925b71 100644
--- a/crates/ra_assists/src/assists/add_derive.rs
+++ b/crates/ra_assists/src/assists/add_derive.rs
@@ -26,7 +26,7 @@ use crate::{Assist, AssistCtx, AssistId};
26// } 26// }
27// ``` 27// ```
28pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 28pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
29 let nominal = ctx.node_at_offset::<ast::NominalDef>()?; 29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
30 let node_start = derive_insertion_offset(&nominal)?; 30 let node_start = derive_insertion_offset(&nominal)?;
31 ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { 31 ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| {
32 let derive_attr = nominal 32 let derive_attr = nominal
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 2903c1781..ffbdc0b62 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -22,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
22// } 22// }
23// ``` 23// ```
24pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 24pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
25 let stmt = ctx.node_at_offset::<LetStmt>()?; 25 let stmt = ctx.find_node_at_offset::<LetStmt>()?;
26 let expr = stmt.initializer()?; 26 let expr = stmt.initializer()?;
27 let pat = stmt.pat()?; 27 let pat = stmt.pat()?;
28 // Must be a binding 28 // Must be a binding
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs
index 142777b06..fd3588d24 100644
--- a/crates/ra_assists/src/assists/add_impl.rs
+++ b/crates/ra_assists/src/assists/add_impl.rs
@@ -28,7 +28,7 @@ use crate::{Assist, AssistCtx, AssistId};
28// } 28// }
29// ``` 29// ```
30pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 30pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
31 let nominal = ctx.node_at_offset::<ast::NominalDef>()?; 31 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
32 let name = nominal.name()?; 32 let name = nominal.name()?;
33 ctx.add_action(AssistId("add_impl"), "add impl", |edit| { 33 ctx.add_action(AssistId("add_impl"), "add impl", |edit| {
34 edit.target(nominal.syntax().text_range()); 34 edit.target(nominal.syntax().text_range());
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index 4ee4d47fa..2585f3045 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -96,7 +96,7 @@ fn add_missing_impl_members_inner(
96 assist_id: &'static str, 96 assist_id: &'static str,
97 label: &'static str, 97 label: &'static str,
98) -> Option<Assist> { 98) -> Option<Assist> {
99 let impl_node = ctx.node_at_offset::<ast::ImplBlock>()?; 99 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?;
100 let impl_item_list = impl_node.item_list()?; 100 let impl_item_list = impl_node.item_list()?;
101 101
102 let trait_def = { 102 let trait_def = {
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
index 75144cefe..8d5984a58 100644
--- a/crates/ra_assists/src/assists/apply_demorgan.rs
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -24,7 +24,7 @@ use crate::{Assist, AssistCtx, AssistId};
24// } 24// }
25// ``` 25// ```
26pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 26pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 let expr = ctx.node_at_offset::<ast::BinExpr>()?; 27 let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
28 let op = expr.op_kind()?; 28 let op = expr.op_kind()?;
29 let op_range = expr.op_token()?.text_range(); 29 let op_range = expr.op_token()?.text_range();
30 let opposite_op = opposite_logic_op(op)?; 30 let opposite_op = opposite_logic_op(op)?;
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs
index 02c58e7c6..a1c2aaa72 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/auto_import.rs
@@ -547,7 +547,7 @@ pub fn auto_import_text_edit(
547} 547}
548 548
549pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 549pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
550 let path: ast::Path = ctx.node_at_offset()?; 550 let path: ast::Path = ctx.find_node_at_offset()?;
551 // We don't want to mess with use statements 551 // We don't want to mess with use statements
552 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { 552 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
553 return None; 553 return None;
diff --git a/crates/ra_assists/src/assists/change_visibility.rs b/crates/ra_assists/src/assists/change_visibility.rs
index bed343677..770ea04fa 100644
--- a/crates/ra_assists/src/assists/change_visibility.rs
+++ b/crates/ra_assists/src/assists/change_visibility.rs
@@ -23,7 +23,7 @@ use crate::{Assist, AssistCtx, AssistId};
23// pub(crate) fn frobnicate() {} 23// pub(crate) fn frobnicate() {}
24// ``` 24// ```
25pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 25pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
26 if let Some(vis) = ctx.node_at_offset::<ast::Visibility>() { 26 if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
27 return change_vis(ctx, vis); 27 return change_vis(ctx, vis);
28 } 28 }
29 add_vis(ctx) 29 add_vis(ctx)
diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs
index 48782db42..75822dc65 100644
--- a/crates/ra_assists/src/assists/early_return.rs
+++ b/crates/ra_assists/src/assists/early_return.rs
@@ -36,7 +36,7 @@ use crate::{
36// } 36// }
37// ``` 37// ```
38pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 38pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
39 let if_expr: ast::IfExpr = ctx.node_at_offset()?; 39 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
40 let expr = if_expr.condition()?.expr()?; 40 let expr = if_expr.condition()?.expr()?;
41 let then_block = if_expr.then_branch()?.block()?; 41 let then_block = if_expr.then_branch()?.block()?;
42 if if_expr.else_branch().is_some() { 42 if if_expr.else_branch().is_some() {
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index b6166f947..c62c0efbe 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -32,7 +32,7 @@ use crate::{Assist, AssistCtx, AssistId};
32// } 32// }
33// ``` 33// ```
34pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 34pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?; 35 let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
36 let match_arm_list = match_expr.match_arm_list()?; 36 let match_arm_list = match_expr.match_arm_list()?;
37 37
38 // We already have some match arms, so we don't provide any assists. 38 // We already have some match arms, so we don't provide any assists.
diff --git a/crates/ra_assists/src/assists/flip_binexpr.rs b/crates/ra_assists/src/assists/flip_binexpr.rs
index 3a1e5cbe1..9765d5ddd 100644
--- a/crates/ra_assists/src/assists/flip_binexpr.rs
+++ b/crates/ra_assists/src/assists/flip_binexpr.rs
@@ -19,7 +19,7 @@ use crate::{Assist, AssistCtx, AssistId};
19// } 19// }
20// ``` 20// ```
21pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 21pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
22 let expr = ctx.node_at_offset::<BinExpr>()?; 22 let expr = ctx.find_node_at_offset::<BinExpr>()?;
23 let lhs = expr.lhs()?.syntax().clone(); 23 let lhs = expr.lhs()?.syntax().clone();
24 let rhs = expr.rhs()?.syntax().clone(); 24 let rhs = expr.rhs()?.syntax().clone();
25 let op_range = expr.op_token()?.text_range(); 25 let op_range = expr.op_token()?.text_range();
diff --git a/crates/ra_assists/src/assists/flip_comma.rs b/crates/ra_assists/src/assists/flip_comma.rs
index d06c5a0e1..53ba8011d 100644
--- a/crates/ra_assists/src/assists/flip_comma.rs
+++ b/crates/ra_assists/src/assists/flip_comma.rs
@@ -19,7 +19,7 @@ use crate::{Assist, AssistCtx, AssistId};
19// } 19// }
20// ``` 20// ```
21pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 21pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
22 let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?; 22 let comma = ctx.find_token_at_offset(T![,])?;
23 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; 23 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
24 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; 24 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
25 25
diff --git a/crates/ra_assists/src/assists/inline_local_variable.rs b/crates/ra_assists/src/assists/inline_local_variable.rs
index 1997781db..fe8fa2a86 100644
--- a/crates/ra_assists/src/assists/inline_local_variable.rs
+++ b/crates/ra_assists/src/assists/inline_local_variable.rs
@@ -24,7 +24,7 @@ use crate::{Assist, AssistCtx, AssistId};
24// } 24// }
25// ``` 25// ```
26pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 26pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 let let_stmt = ctx.node_at_offset::<ast::LetStmt>()?; 27 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
28 let bind_pat = match let_stmt.pat()? { 28 let bind_pat = match let_stmt.pat()? {
29 ast::Pat::BindPat(pat) => pat, 29 ast::Pat::BindPat(pat) => pat,
30 _ => return None, 30 _ => return None,
diff --git a/crates/ra_assists/src/assists/merge_match_arms.rs b/crates/ra_assists/src/assists/merge_match_arms.rs
index f5ddd7159..b0c4ee78b 100644
--- a/crates/ra_assists/src/assists/merge_match_arms.rs
+++ b/crates/ra_assists/src/assists/merge_match_arms.rs
@@ -27,7 +27,7 @@ use ra_syntax::ast::{AstNode, MatchArm};
27// } 27// }
28// ``` 28// ```
29pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 29pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
30 let current_arm = ctx.node_at_offset::<MatchArm>()?; 30 let current_arm = ctx.find_node_at_offset::<MatchArm>()?;
31 31
32 // We check if the following match arm matches this one. We could, but don't, 32 // We check if the following match arm matches this one. We could, but don't,
33 // compare to the previous match arm as well. 33 // compare to the previous match arm as well.
diff --git a/crates/ra_assists/src/assists/move_bounds.rs b/crates/ra_assists/src/assists/move_bounds.rs
index f96e19a9f..edf2897c6 100644
--- a/crates/ra_assists/src/assists/move_bounds.rs
+++ b/crates/ra_assists/src/assists/move_bounds.rs
@@ -23,7 +23,7 @@ use crate::{Assist, AssistCtx, AssistId};
23// } 23// }
24// ``` 24// ```
25pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 25pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
26 let type_param_list = ctx.node_at_offset::<ast::TypeParamList>()?; 26 let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
27 27
28 let mut type_params = type_param_list.type_params(); 28 let mut type_params = type_param_list.type_params();
29 if type_params.all(|p| p.type_bound_list().is_none()) { 29 if type_params.all(|p| p.type_bound_list().is_none()) {
diff --git a/crates/ra_assists/src/assists/move_guard.rs b/crates/ra_assists/src/assists/move_guard.rs
index 36c95128d..e820a73c8 100644
--- a/crates/ra_assists/src/assists/move_guard.rs
+++ b/crates/ra_assists/src/assists/move_guard.rs
@@ -33,7 +33,7 @@ use crate::{Assist, AssistCtx, AssistId};
33// } 33// }
34// ``` 34// ```
35pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 35pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
36 let match_arm = ctx.node_at_offset::<MatchArm>()?; 36 let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
37 let guard = match_arm.guard()?; 37 let guard = match_arm.guard()?;
38 let space_before_guard = guard.syntax().prev_sibling_or_token(); 38 let space_before_guard = guard.syntax().prev_sibling_or_token();
39 39
@@ -91,7 +91,7 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
91// } 91// }
92// ``` 92// ```
93pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 93pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
94 let match_arm: MatchArm = ctx.node_at_offset::<MatchArm>()?; 94 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
95 let last_match_pat = match_arm.pats().last()?; 95 let last_match_pat = match_arm.pats().last()?;
96 96
97 let arm_body = match_arm.expr()?; 97 let arm_body = match_arm.expr()?;
diff --git a/crates/ra_assists/src/assists/raw_string.rs b/crates/ra_assists/src/assists/raw_string.rs
index 2d2e31e51..ea756d1ca 100644
--- a/crates/ra_assists/src/assists/raw_string.rs
+++ b/crates/ra_assists/src/assists/raw_string.rs
@@ -1,17 +1,16 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::db::HirDatabase; 3use hir::db::HirDatabase;
4use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; 4use ra_syntax::{
5 SyntaxKind::{RAW_STRING, STRING},
6 TextRange, TextUnit,
7};
5use rustc_lexer; 8use rustc_lexer;
6 9
7use crate::{Assist, AssistCtx, AssistId}; 10use crate::{Assist, AssistCtx, AssistId};
8 11
9pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 12pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
10 let literal = ctx.node_at_offset::<Literal>()?; 13 let token = ctx.find_token_at_offset(STRING)?;
11 if literal.token().kind() != ra_syntax::SyntaxKind::STRING {
12 return None;
13 }
14 let token = literal.token();
15 let text = token.text().as_str(); 14 let text = token.text().as_str();
16 let usual_string_range = find_usual_string_range(text)?; 15 let usual_string_range = find_usual_string_range(text)?;
17 let start_of_inside = usual_string_range.start().to_usize() + 1; 16 let start_of_inside = usual_string_range.start().to_usize() + 1;
@@ -30,85 +29,52 @@ pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
30 return None; 29 return None;
31 } 30 }
32 ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| { 31 ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| {
33 edit.target(literal.syntax().text_range()); 32 edit.target(token.text_range());
34 let max_hash_streak = count_hashes(&unescaped); 33 let max_hash_streak = count_hashes(&unescaped);
35 let mut hashes = String::with_capacity(max_hash_streak + 1); 34 let mut hashes = String::with_capacity(max_hash_streak + 1);
36 for _ in 0..hashes.capacity() { 35 for _ in 0..hashes.capacity() {
37 hashes.push('#'); 36 hashes.push('#');
38 } 37 }
39 edit.replace( 38 edit.replace(token.text_range(), format!("r{}\"{}\"{}", hashes, unescaped, hashes));
40 literal.syntax().text_range(),
41 format!("r{}\"{}\"{}", hashes, unescaped, hashes),
42 );
43 }); 39 });
44 ctx.build() 40 ctx.build()
45} 41}
46 42
47fn count_hashes(s: &str) -> usize {
48 let mut max_hash_streak = 0usize;
49 for idx in s.match_indices("\"#").map(|(i, _)| i) {
50 let (_, sub) = s.split_at(idx + 1);
51 let nb_hash = sub.chars().take_while(|c| *c == '#').count();
52 if nb_hash > max_hash_streak {
53 max_hash_streak = nb_hash;
54 }
55 }
56 max_hash_streak
57}
58
59fn find_usual_string_range(s: &str) -> Option<TextRange> {
60 Some(TextRange::from_to(
61 TextUnit::from(s.find('"')? as u32),
62 TextUnit::from(s.rfind('"')? as u32),
63 ))
64}
65
66pub(crate) fn make_usual_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 43pub(crate) fn make_usual_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
67 let literal = ctx.node_at_offset::<Literal>()?; 44 let token = ctx.find_token_at_offset(RAW_STRING)?;
68 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
69 return None;
70 }
71 let token = literal.token();
72 let text = token.text().as_str(); 45 let text = token.text().as_str();
73 let usual_string_range = find_usual_string_range(text)?; 46 let usual_string_range = find_usual_string_range(text)?;
74 ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| { 47 ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| {
75 edit.target(literal.syntax().text_range()); 48 edit.target(token.text_range());
76 // parse inside string to escape `"` 49 // parse inside string to escape `"`
77 let start_of_inside = usual_string_range.start().to_usize() + 1; 50 let start_of_inside = usual_string_range.start().to_usize() + 1;
78 let end_of_inside = usual_string_range.end().to_usize(); 51 let end_of_inside = usual_string_range.end().to_usize();
79 let inside_str = &text[start_of_inside..end_of_inside]; 52 let inside_str = &text[start_of_inside..end_of_inside];
80 let escaped = inside_str.escape_default().to_string(); 53 let escaped = inside_str.escape_default().to_string();
81 edit.replace(literal.syntax().text_range(), format!("\"{}\"", escaped)); 54 edit.replace(token.text_range(), format!("\"{}\"", escaped));
82 }); 55 });
83 ctx.build() 56 ctx.build()
84} 57}
85 58
86pub(crate) fn add_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 59pub(crate) fn add_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
87 let literal = ctx.node_at_offset::<Literal>()?; 60 let token = ctx.find_token_at_offset(RAW_STRING)?;
88 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
89 return None;
90 }
91 ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| { 61 ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| {
92 edit.target(literal.syntax().text_range()); 62 edit.target(token.text_range());
93 edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#"); 63 edit.insert(token.text_range().start() + TextUnit::of_char('r'), "#");
94 edit.insert(literal.syntax().text_range().end(), "#"); 64 edit.insert(token.text_range().end(), "#");
95 }); 65 });
96 ctx.build() 66 ctx.build()
97} 67}
98 68
99pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 69pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
100 let literal = ctx.node_at_offset::<Literal>()?; 70 let token = ctx.find_token_at_offset(RAW_STRING)?;
101 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
102 return None;
103 }
104 let token = literal.token();
105 let text = token.text().as_str(); 71 let text = token.text().as_str();
106 if text.starts_with("r\"") { 72 if text.starts_with("r\"") {
107 // no hash to remove 73 // no hash to remove
108 return None; 74 return None;
109 } 75 }
110 ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| { 76 ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| {
111 edit.target(literal.syntax().text_range()); 77 edit.target(token.text_range());
112 let result = &text[2..text.len() - 1]; 78 let result = &text[2..text.len() - 1];
113 let result = if result.starts_with("\"") { 79 let result = if result.starts_with("\"") {
114 // no more hash, escape 80 // no more hash, escape
@@ -117,11 +83,30 @@ pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
117 } else { 83 } else {
118 result.to_owned() 84 result.to_owned()
119 }; 85 };
120 edit.replace(literal.syntax().text_range(), format!("r{}", result)); 86 edit.replace(token.text_range(), format!("r{}", result));
121 }); 87 });
122 ctx.build() 88 ctx.build()
123} 89}
124 90
91fn count_hashes(s: &str) -> usize {
92 let mut max_hash_streak = 0usize;
93 for idx in s.match_indices("\"#").map(|(i, _)| i) {
94 let (_, sub) = s.split_at(idx + 1);
95 let nb_hash = sub.chars().take_while(|c| *c == '#').count();
96 if nb_hash > max_hash_streak {
97 max_hash_streak = nb_hash;
98 }
99 }
100 max_hash_streak
101}
102
103fn find_usual_string_range(s: &str) -> Option<TextRange> {
104 Some(TextRange::from_to(
105 TextUnit::from(s.find('"')? as u32),
106 TextUnit::from(s.rfind('"')? as u32),
107 ))
108}
109
125#[cfg(test)] 110#[cfg(test)]
126mod test { 111mod test {
127 use super::*; 112 use super::*;
@@ -159,6 +144,23 @@ string"#;
159 } 144 }
160 145
161 #[test] 146 #[test]
147 fn make_raw_string_works_inside_macros() {
148 check_assist(
149 make_raw_string,
150 r#"
151 fn f() {
152 format!(<|>"x = {}", 92)
153 }
154 "#,
155 r##"
156 fn f() {
157 format!(<|>r#"x = {}"#, 92)
158 }
159 "##,
160 )
161 }
162
163 #[test]
162 fn make_raw_string_hashes_inside_works() { 164 fn make_raw_string_hashes_inside_works() {
163 check_assist( 165 check_assist(
164 make_raw_string, 166 make_raw_string,
diff --git a/crates/ra_assists/src/assists/remove_dbg.rs b/crates/ra_assists/src/assists/remove_dbg.rs
index 1a7e2b305..ac2c43e1a 100644
--- a/crates/ra_assists/src/assists/remove_dbg.rs
+++ b/crates/ra_assists/src/assists/remove_dbg.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
8}; 8};
9 9
10pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let macro_call = ctx.node_at_offset::<ast::MacroCall>()?; 11 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
12 12
13 if !is_valid_macrocall(&macro_call, "dbg")? { 13 if !is_valid_macrocall(&macro_call, "dbg")? {
14 return None; 14 return None;
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
index 749ff338a..da276e47b 100644
--- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
@@ -8,7 +8,7 @@ use ra_syntax::{ast, AstNode};
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
9 9
10pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let if_expr: ast::IfExpr = ctx.node_at_offset()?; 11 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
12 let cond = if_expr.condition()?; 12 let cond = if_expr.condition()?;
13 let pat = cond.pat()?; 13 let pat = cond.pat()?;
14 let expr = cond.expr()?; 14 let expr = cond.expr()?;
diff --git a/crates/ra_assists/src/assists/split_import.rs b/crates/ra_assists/src/assists/split_import.rs
index fe3e64af5..09bde1b72 100644
--- a/crates/ra_assists/src/assists/split_import.rs
+++ b/crates/ra_assists/src/assists/split_import.rs
@@ -8,7 +8,7 @@ use ra_syntax::{ast, AstNode, TextUnit, T};
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
9 9
10pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == T![::])?; 11 let colon_colon = ctx.find_token_at_offset(T![::])?;
12 let path = ast::Path::cast(colon_colon.parent())?; 12 let path = ast::Path::cast(colon_colon.parent())?;
13 let top_path = successors(Some(path), |it| it.parent_path()).last()?; 13 let top_path = successors(Some(path), |it| it.parent_path()).last()?;
14 14