diff options
-rw-r--r-- | crates/ra_assists/src/handlers/raw_string.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/injection.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/tokens.rs | 17 |
4 files changed, 35 insertions, 17 deletions
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index 96679e160..6d77dff13 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | use std::borrow::Cow; | ||
2 | |||
1 | use ra_syntax::{ | 3 | use ra_syntax::{ |
2 | ast::{self, HasStringValue}, | 4 | ast::{self, HasQuotes, HasStringValue}, |
3 | AstToken, | 5 | AstToken, |
4 | SyntaxKind::{RAW_STRING, STRING}, | 6 | SyntaxKind::{RAW_STRING, STRING}, |
5 | TextSize, | 7 | TextSize, |
@@ -32,14 +34,17 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
32 | target, | 34 | target, |
33 | |edit| { | 35 | |edit| { |
34 | let max_hash_streak = count_hashes(&value); | 36 | let max_hash_streak = count_hashes(&value); |
35 | let mut hashes = String::with_capacity(max_hash_streak + 1); | 37 | let hashes = "#".repeat(max_hash_streak + 1); |
36 | for _ in 0..hashes.capacity() { | 38 | if matches!(value, Cow::Borrowed(_)) { |
37 | hashes.push('#'); | 39 | // Avoid replacing the whole string to better position the cursor. |
38 | } | 40 | edit.insert(token.syntax().text_range().start(), format!("r{}", hashes)); |
39 | edit.replace( | 41 | edit.insert(token.syntax().text_range().end(), format!("{}", hashes)); |
40 | token.syntax().text_range(), | 42 | } else { |
41 | format!("r{}\"{}\"{}", hashes, value, hashes), | 43 | edit.replace( |
42 | ); | 44 | token.syntax().text_range(), |
45 | format!("r{}\"{}\"{}", hashes, value, hashes), | ||
46 | ); | ||
47 | } | ||
43 | }, | 48 | }, |
44 | ) | 49 | ) |
45 | } | 50 | } |
@@ -70,6 +75,14 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
70 | |edit| { | 75 | |edit| { |
71 | // parse inside string to escape `"` | 76 | // parse inside string to escape `"` |
72 | let escaped = value.escape_default().to_string(); | 77 | let escaped = value.escape_default().to_string(); |
78 | if let Some(offsets) = token.quote_offsets() { | ||
79 | if token.text()[offsets.contents - token.syntax().text_range().start()] == escaped { | ||
80 | edit.replace(offsets.quotes.0, "\""); | ||
81 | edit.replace(offsets.quotes.1, "\""); | ||
82 | return; | ||
83 | } | ||
84 | } | ||
85 | |||
73 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); | 86 | edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); |
74 | }, | 87 | }, |
75 | ) | 88 | ) |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 626f9efd0..9f50569dc 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -272,7 +272,7 @@ fn format_args_expand( | |||
272 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 272 | fn unquote_str(lit: &tt::Literal) -> Option<String> { |
273 | let lit = ast::make::tokens::literal(&lit.to_string()); | 273 | let lit = ast::make::tokens::literal(&lit.to_string()); |
274 | let token = ast::String::cast(lit)?; | 274 | let token = ast::String::cast(lit)?; |
275 | token.value() | 275 | token.value().map(|it| it.into_owned()) |
276 | } | 276 | } |
277 | 277 | ||
278 | fn concat_expand( | 278 | fn concat_expand( |
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index 181c21256..8665b480f 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs | |||
@@ -25,7 +25,7 @@ pub(super) fn highlight_injection( | |||
25 | return None; | 25 | return None; |
26 | } | 26 | } |
27 | let value = literal.value()?; | 27 | let value = literal.value()?; |
28 | let (analysis, tmp_file_id) = Analysis::from_single_file(value); | 28 | let (analysis, tmp_file_id) = Analysis::from_single_file(value.into_owned()); |
29 | 29 | ||
30 | if let Some(range) = literal.open_quote_text_range() { | 30 | if let Some(range) = literal.open_quote_text_range() { |
31 | acc.add(HighlightedRange { | 31 | acc.add(HighlightedRange { |
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs index 2e72d4927..045f69133 100644 --- a/crates/ra_syntax/src/ast/tokens.rs +++ b/crates/ra_syntax/src/ast/tokens.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | //! There are many AstNodes, but only a few tokens, so we hand-write them here. | 1 | //! There are many AstNodes, but only a few tokens, so we hand-write them here. |
2 | 2 | ||
3 | use std::convert::{TryFrom, TryInto}; | 3 | use std::{ |
4 | borrow::Cow, | ||
5 | convert::{TryFrom, TryInto}, | ||
6 | }; | ||
4 | 7 | ||
5 | use crate::{ | 8 | use crate::{ |
6 | ast::{AstToken, Comment, RawString, String, Whitespace}, | 9 | ast::{AstToken, Comment, RawString, String, Whitespace}, |
@@ -138,11 +141,11 @@ impl HasQuotes for String {} | |||
138 | impl HasQuotes for RawString {} | 141 | impl HasQuotes for RawString {} |
139 | 142 | ||
140 | pub trait HasStringValue: HasQuotes { | 143 | pub trait HasStringValue: HasQuotes { |
141 | fn value(&self) -> Option<std::string::String>; | 144 | fn value(&self) -> Option<Cow<'_, str>>; |
142 | } | 145 | } |
143 | 146 | ||
144 | impl HasStringValue for String { | 147 | impl HasStringValue for String { |
145 | fn value(&self) -> Option<std::string::String> { | 148 | fn value(&self) -> Option<Cow<'_, str>> { |
146 | let text = self.text().as_str(); | 149 | let text = self.text().as_str(); |
147 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; | 150 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; |
148 | 151 | ||
@@ -156,15 +159,17 @@ impl HasStringValue for String { | |||
156 | if has_error { | 159 | if has_error { |
157 | return None; | 160 | return None; |
158 | } | 161 | } |
159 | Some(buf) | 162 | // FIXME: don't actually allocate for borrowed case |
163 | let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) }; | ||
164 | Some(res) | ||
160 | } | 165 | } |
161 | } | 166 | } |
162 | 167 | ||
163 | impl HasStringValue for RawString { | 168 | impl HasStringValue for RawString { |
164 | fn value(&self) -> Option<std::string::String> { | 169 | fn value(&self) -> Option<Cow<'_, str>> { |
165 | let text = self.text().as_str(); | 170 | let text = self.text().as_str(); |
166 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; | 171 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; |
167 | Some(text.to_string()) | 172 | Some(Cow::Borrowed(text)) |
168 | } | 173 | } |
169 | } | 174 | } |
170 | 175 | ||