diff options
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 20 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/join_lines.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 2 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/raw_string.rs | 2 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/replace_string_with_char.rs | 2 | ||||
-rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 81 |
8 files changed, 85 insertions, 33 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 9f278d35b..b00dcbdf0 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -1022,7 +1022,10 @@ impl From<ast::LiteralKind> for Literal { | |||
1022 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1022 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); |
1023 | Literal::Float(Default::default(), ty) | 1023 | Literal::Float(Default::default(), ty) |
1024 | } | 1024 | } |
1025 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), | 1025 | LiteralKind::ByteString(bs) => { |
1026 | let text = bs.value().map(Vec::from).unwrap_or_else(Default::default); | ||
1027 | Literal::ByteString(text) | ||
1028 | } | ||
1026 | LiteralKind::String(_) => Literal::String(Default::default()), | 1029 | LiteralKind::String(_) => Literal::String(Default::default()), |
1027 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), | 1030 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), |
1028 | LiteralKind::Bool(val) => Literal::Bool(val), | 1031 | LiteralKind::Bool(val) => Literal::Bool(val), |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 5e9420752..46e4777a4 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -16,7 +16,7 @@ use stdx::always; | |||
16 | use syntax::ast::RangeOp; | 16 | use syntax::ast::RangeOp; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | autoderef, dummy_usize_const, | 19 | autoderef, |
20 | lower::lower_to_chalk_mutability, | 20 | lower::lower_to_chalk_mutability, |
21 | mapping::from_chalk, | 21 | mapping::from_chalk, |
22 | method_resolution, op, | 22 | method_resolution, op, |
@@ -24,8 +24,9 @@ use crate::{ | |||
24 | static_lifetime, to_chalk_trait_id, | 24 | static_lifetime, to_chalk_trait_id, |
25 | traits::FnTrait, | 25 | traits::FnTrait, |
26 | utils::{generics, Generics}, | 26 | utils::{generics, Generics}, |
27 | AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner, | 27 | AdtId, Binders, CallableDefId, ConcreteConst, ConstValue, FnPointer, FnSig, FnSubst, |
28 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, | 28 | InEnvironment, Interner, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, |
29 | TyBuilder, TyExt, TyKind, | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | use super::{ | 32 | use super::{ |
@@ -758,11 +759,18 @@ impl<'a> InferenceContext<'a> { | |||
758 | TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner)) | 759 | TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner)) |
759 | .intern(&Interner) | 760 | .intern(&Interner) |
760 | } | 761 | } |
761 | Literal::ByteString(..) => { | 762 | Literal::ByteString(bs) => { |
762 | let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); | 763 | let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); |
763 | 764 | ||
764 | let array_type = | 765 | let len = ConstData { |
765 | TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); | 766 | ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), |
767 | value: ConstValue::Concrete(ConcreteConst { | ||
768 | interned: ConstScalar::Usize(bs.len() as u64), | ||
769 | }), | ||
770 | } | ||
771 | .intern(&Interner); | ||
772 | |||
773 | let array_type = TyKind::Array(byte_type, len).intern(&Interner); | ||
766 | TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) | 774 | TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) |
767 | } | 775 | } |
768 | Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), | 776 | Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 19775a4ec..79445a12d 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -496,7 +496,7 @@ fn infer_literals() { | |||
496 | 26..30 '5f32': f32 | 496 | 26..30 '5f32': f32 |
497 | 36..40 '5f64': f64 | 497 | 36..40 '5f64': f64 |
498 | 46..53 '"hello"': &str | 498 | 46..53 '"hello"': &str |
499 | 59..67 'b"bytes"': &[u8; _] | 499 | 59..67 'b"bytes"': &[u8; 5] |
500 | 73..76 ''c'': char | 500 | 73..76 ''c'': char |
501 | 82..86 'b'b'': u8 | 501 | 82..86 'b'b'': u8 |
502 | 92..96 '3.14': f64 | 502 | 92..96 '3.14': f64 |
@@ -504,7 +504,7 @@ fn infer_literals() { | |||
504 | 112..117 'false': bool | 504 | 112..117 'false': bool |
505 | 123..127 'true': bool | 505 | 123..127 'true': bool |
506 | 133..197 'r#" ... "#': &str | 506 | 133..197 'r#" ... "#': &str |
507 | 203..213 'br#"yolo"#': &[u8; _] | 507 | 203..213 'br#"yolo"#': &[u8; 4] |
508 | "##]], | 508 | "##]], |
509 | ); | 509 | ); |
510 | } | 510 | } |
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 61dcbb399..c67ccd1a9 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -4,7 +4,7 @@ use ide_assists::utils::extract_trivial_expression; | |||
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo::non_trivia_sibling, | 6 | algo::non_trivia_sibling, |
7 | ast::{self, AstNode, AstToken}, | 7 | ast::{self, AstNode, AstToken, IsString}, |
8 | Direction, NodeOrToken, SourceFile, | 8 | Direction, NodeOrToken, SourceFile, |
9 | SyntaxKind::{self, USE_TREE, WHITESPACE}, | 9 | SyntaxKind::{self, USE_TREE, WHITESPACE}, |
10 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, | 10 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, |
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index bc221d599..4269d339e 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -6,7 +6,7 @@ use either::Either; | |||
6 | use hir::{InFile, Semantics}; | 6 | use hir::{InFile, Semantics}; |
7 | use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind}; | 7 | use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind}; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | ast::{self, AstNode}, | 9 | ast::{self, AstNode, IsString}, |
10 | AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, | 10 | AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, |
11 | }; | 11 | }; |
12 | 12 | ||
diff --git a/crates/ide_assists/src/handlers/raw_string.rs b/crates/ide_assists/src/handlers/raw_string.rs index d0f1613f3..d98a55ae4 100644 --- a/crates/ide_assists/src/handlers/raw_string.rs +++ b/crates/ide_assists/src/handlers/raw_string.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::borrow::Cow; | 1 | use std::borrow::Cow; |
2 | 2 | ||
3 | use syntax::{ast, AstToken, TextRange, TextSize}; | 3 | use syntax::{ast, ast::IsString, AstToken, TextRange, TextSize}; |
4 | 4 | ||
5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
6 | 6 | ||
diff --git a/crates/ide_assists/src/handlers/replace_string_with_char.rs b/crates/ide_assists/src/handlers/replace_string_with_char.rs index 634b9c0b7..0800d291e 100644 --- a/crates/ide_assists/src/handlers/replace_string_with_char.rs +++ b/crates/ide_assists/src/handlers/replace_string_with_char.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use syntax::{ast, AstToken, SyntaxKind::STRING}; | 1 | use syntax::{ast, ast::IsString, AstToken, SyntaxKind::STRING}; |
2 | 2 | ||
3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
4 | 4 | ||
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 29d25a58a..4b1e1ccee 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -143,6 +143,30 @@ impl QuoteOffsets { | |||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | pub trait IsString: AstToken { | ||
147 | fn quote_offsets(&self) -> Option<QuoteOffsets> { | ||
148 | let text = self.text(); | ||
149 | let offsets = QuoteOffsets::new(text)?; | ||
150 | let o = self.syntax().text_range().start(); | ||
151 | let offsets = QuoteOffsets { | ||
152 | quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o), | ||
153 | contents: offsets.contents + o, | ||
154 | }; | ||
155 | Some(offsets) | ||
156 | } | ||
157 | fn text_range_between_quotes(&self) -> Option<TextRange> { | ||
158 | self.quote_offsets().map(|it| it.contents) | ||
159 | } | ||
160 | fn open_quote_text_range(&self) -> Option<TextRange> { | ||
161 | self.quote_offsets().map(|it| it.quotes.0) | ||
162 | } | ||
163 | fn close_quote_text_range(&self) -> Option<TextRange> { | ||
164 | self.quote_offsets().map(|it| it.quotes.1) | ||
165 | } | ||
166 | } | ||
167 | |||
168 | impl IsString for ast::String {} | ||
169 | |||
146 | impl ast::String { | 170 | impl ast::String { |
147 | pub fn is_raw(&self) -> bool { | 171 | pub fn is_raw(&self) -> bool { |
148 | self.text().starts_with('r') | 172 | self.text().starts_with('r') |
@@ -187,32 +211,49 @@ impl ast::String { | |||
187 | (false, false) => Some(Cow::Owned(buf)), | 211 | (false, false) => Some(Cow::Owned(buf)), |
188 | } | 212 | } |
189 | } | 213 | } |
190 | |||
191 | pub fn quote_offsets(&self) -> Option<QuoteOffsets> { | ||
192 | let text = self.text(); | ||
193 | let offsets = QuoteOffsets::new(text)?; | ||
194 | let o = self.syntax().text_range().start(); | ||
195 | let offsets = QuoteOffsets { | ||
196 | quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o), | ||
197 | contents: offsets.contents + o, | ||
198 | }; | ||
199 | Some(offsets) | ||
200 | } | ||
201 | pub fn text_range_between_quotes(&self) -> Option<TextRange> { | ||
202 | self.quote_offsets().map(|it| it.contents) | ||
203 | } | ||
204 | pub fn open_quote_text_range(&self) -> Option<TextRange> { | ||
205 | self.quote_offsets().map(|it| it.quotes.0) | ||
206 | } | ||
207 | pub fn close_quote_text_range(&self) -> Option<TextRange> { | ||
208 | self.quote_offsets().map(|it| it.quotes.1) | ||
209 | } | ||
210 | } | 214 | } |
211 | 215 | ||
216 | impl IsString for ast::ByteString {} | ||
217 | |||
212 | impl ast::ByteString { | 218 | impl ast::ByteString { |
213 | pub fn is_raw(&self) -> bool { | 219 | pub fn is_raw(&self) -> bool { |
214 | self.text().starts_with("br") | 220 | self.text().starts_with("br") |
215 | } | 221 | } |
222 | |||
223 | pub fn value(&self) -> Option<Cow<'_, [u8]>> { | ||
224 | if self.is_raw() { | ||
225 | let text = self.text(); | ||
226 | let text = | ||
227 | &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; | ||
228 | return Some(Cow::Borrowed(text.as_bytes())); | ||
229 | } | ||
230 | |||
231 | let text = self.text(); | ||
232 | let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; | ||
233 | |||
234 | let mut buf: Vec<u8> = Vec::new(); | ||
235 | let mut text_iter = text.chars(); | ||
236 | let mut has_error = false; | ||
237 | unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match ( | ||
238 | unescaped_char, | ||
239 | buf.capacity() == 0, | ||
240 | ) { | ||
241 | (Ok(c), false) => buf.push(c as u8), | ||
242 | (Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (), | ||
243 | (Ok(c), true) => { | ||
244 | buf.reserve_exact(text.len()); | ||
245 | buf.extend_from_slice(&text[..char_range.start].as_bytes()); | ||
246 | buf.push(c as u8); | ||
247 | } | ||
248 | (Err(_), _) => has_error = true, | ||
249 | }); | ||
250 | |||
251 | match (has_error, buf.capacity() == 0) { | ||
252 | (true, _) => None, | ||
253 | (false, true) => Some(Cow::Borrowed(text.as_bytes())), | ||
254 | (false, false) => Some(Cow::Owned(buf)), | ||
255 | } | ||
256 | } | ||
216 | } | 257 | } |
217 | 258 | ||
218 | #[derive(Debug)] | 259 | #[derive(Debug)] |