diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-10-17 12:21:00 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-10-17 12:21:00 +0100 |
commit | 762fce5bdd166144c33871ae5b2594684eb0169e (patch) | |
tree | 4400f468ee88b2b7b3efb5d7bf61e8fb7512f816 /crates/ra_ide_api/src/completion | |
parent | 84d9fd1864a162170f6b49a9ca871c3101b149b3 (diff) | |
parent | bec47e221fbd78a2e5f253e9418c4b86e243e35a (diff) |
Merge #2012
2012: #1435 postfix completion for integer literals r=matklad a=pasa
Fix for #1435 Incorrect postfix completion for integer literals
Co-authored-by: Sergey Parilin <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/completion')
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_postfix.rs | 67 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_context.rs | 12 |
2 files changed, 77 insertions, 2 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs index 445a02676..555cecb73 100644 --- a/crates/ra_ide_api/src/completion/complete_postfix.rs +++ b/crates/ra_ide_api/src/completion/complete_postfix.rs | |||
@@ -8,7 +8,7 @@ use crate::{ | |||
8 | CompletionItem, | 8 | CompletionItem, |
9 | }; | 9 | }; |
10 | use hir::{Ty, TypeCtor}; | 10 | use hir::{Ty, TypeCtor}; |
11 | use ra_syntax::{ast::AstNode, TextRange}; | 11 | use ra_syntax::{ast::AstNode, TextRange, TextUnit}; |
12 | use ra_text_edit::TextEditBuilder; | 12 | use ra_text_edit::TextEditBuilder; |
13 | 13 | ||
14 | fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { | 14 | fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { |
@@ -42,7 +42,13 @@ fn is_bool_or_unknown(ty: Option<Ty>) -> bool { | |||
42 | 42 | ||
43 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | 43 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { |
44 | if let Some(dot_receiver) = &ctx.dot_receiver { | 44 | if let Some(dot_receiver) = &ctx.dot_receiver { |
45 | let receiver_text = dot_receiver.syntax().text().to_string(); | 45 | let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal { |
46 | let text = dot_receiver.syntax().text(); | ||
47 | let without_dot = ..text.len() - TextUnit::of_char('.'); | ||
48 | text.slice(without_dot).to_string() | ||
49 | } else { | ||
50 | dot_receiver.syntax().text().to_string() | ||
51 | }; | ||
46 | let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); | 52 | let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); |
47 | if is_bool_or_unknown(receiver_ty) { | 53 | if is_bool_or_unknown(receiver_ty) { |
48 | postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) | 54 | postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) |
@@ -209,4 +215,61 @@ mod tests { | |||
209 | ]"### | 215 | ]"### |
210 | ); | 216 | ); |
211 | } | 217 | } |
218 | |||
219 | #[test] | ||
220 | fn postfix_completion_works_for_ambiguous_float_literal() { | ||
221 | assert_debug_snapshot!( | ||
222 | do_postfix_completion( | ||
223 | r#" | ||
224 | fn main() { | ||
225 | 42.<|> | ||
226 | } | ||
227 | "#, | ||
228 | ), | ||
229 | @r###"[ | ||
230 | CompletionItem { | ||
231 | label: "box", | ||
232 | source_range: [52; 52), | ||
233 | delete: [49; 52), | ||
234 | insert: "Box::new(42)", | ||
235 | detail: "Box::new(expr)", | ||
236 | }, | ||
237 | CompletionItem { | ||
238 | label: "dbg", | ||
239 | source_range: [52; 52), | ||
240 | delete: [49; 52), | ||
241 | insert: "dbg!(42)", | ||
242 | detail: "dbg!(expr)", | ||
243 | }, | ||
244 | CompletionItem { | ||
245 | label: "match", | ||
246 | source_range: [52; 52), | ||
247 | delete: [49; 52), | ||
248 | insert: "match 42 {\n ${1:_} => {$0\\},\n}", | ||
249 | detail: "match expr {}", | ||
250 | }, | ||
251 | CompletionItem { | ||
252 | label: "not", | ||
253 | source_range: [52; 52), | ||
254 | delete: [49; 52), | ||
255 | insert: "!42", | ||
256 | detail: "!expr", | ||
257 | }, | ||
258 | CompletionItem { | ||
259 | label: "ref", | ||
260 | source_range: [52; 52), | ||
261 | delete: [49; 52), | ||
262 | insert: "&42", | ||
263 | detail: "&expr", | ||
264 | }, | ||
265 | CompletionItem { | ||
266 | label: "refm", | ||
267 | source_range: [52; 52), | ||
268 | delete: [49; 52), | ||
269 | insert: "&mut 42", | ||
270 | detail: "&mut expr", | ||
271 | }, | ||
272 | ]"### | ||
273 | ); | ||
274 | } | ||
212 | } | 275 | } |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 73f3f3960..64cbc0f98 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -38,6 +38,7 @@ pub(crate) struct CompletionContext<'a> { | |||
38 | pub(super) is_new_item: bool, | 38 | pub(super) is_new_item: bool, |
39 | /// The receiver if this is a field or method access, i.e. writing something.<|> | 39 | /// The receiver if this is a field or method access, i.e. writing something.<|> |
40 | pub(super) dot_receiver: Option<ast::Expr>, | 40 | pub(super) dot_receiver: Option<ast::Expr>, |
41 | pub(super) dot_receiver_is_ambiguous_float_literal: bool, | ||
41 | /// If this is a call (method or function) in particular, i.e. the () are already there. | 42 | /// If this is a call (method or function) in particular, i.e. the () are already there. |
42 | pub(super) is_call: bool, | 43 | pub(super) is_call: bool, |
43 | pub(super) is_path_type: bool, | 44 | pub(super) is_path_type: bool, |
@@ -80,6 +81,7 @@ impl<'a> CompletionContext<'a> { | |||
80 | is_call: false, | 81 | is_call: false, |
81 | is_path_type: false, | 82 | is_path_type: false, |
82 | has_type_args: false, | 83 | has_type_args: false, |
84 | dot_receiver_is_ambiguous_float_literal: false, | ||
83 | }; | 85 | }; |
84 | ctx.fill(&original_parse, position.offset); | 86 | ctx.fill(&original_parse, position.offset); |
85 | Some(ctx) | 87 | Some(ctx) |
@@ -235,6 +237,16 @@ impl<'a> CompletionContext<'a> { | |||
235 | .expr() | 237 | .expr() |
236 | .map(|e| e.syntax().text_range()) | 238 | .map(|e| e.syntax().text_range()) |
237 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); | 239 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); |
240 | self.dot_receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = | ||
241 | &self.dot_receiver | ||
242 | { | ||
243 | match l.kind() { | ||
244 | ast::LiteralKind::FloatNumber { suffix: _ } => l.token().text().ends_with('.'), | ||
245 | _ => false, | ||
246 | } | ||
247 | } else { | ||
248 | false | ||
249 | } | ||
238 | } | 250 | } |
239 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { | 251 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { |
240 | // As above | 252 | // As above |