From bec47e221fbd78a2e5f253e9418c4b86e243e35a Mon Sep 17 00:00:00 2001 From: Sergey Parilin Date: Mon, 14 Oct 2019 18:39:40 +0300 Subject: #1435 postfix completion for integer literals --- .../ra_ide_api/src/completion/complete_postfix.rs | 67 +++++++++++++++++++++- .../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::{ CompletionItem, }; use hir::{Ty, TypeCtor}; -use ra_syntax::{ast::AstNode, TextRange}; +use ra_syntax::{ast::AstNode, TextRange, TextUnit}; use ra_text_edit::TextEditBuilder; fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { @@ -42,7 +42,13 @@ fn is_bool_or_unknown(ty: Option) -> bool { pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { if let Some(dot_receiver) = &ctx.dot_receiver { - let receiver_text = dot_receiver.syntax().text().to_string(); + let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal { + let text = dot_receiver.syntax().text(); + let without_dot = ..text.len() - TextUnit::of_char('.'); + text.slice(without_dot).to_string() + } else { + dot_receiver.syntax().text().to_string() + }; let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); if is_bool_or_unknown(receiver_ty) { postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) @@ -206,6 +212,63 @@ mod tests { insert: "&mut bar", detail: "&mut expr", }, +]"### + ); + } + + #[test] + fn postfix_completion_works_for_ambiguous_float_literal() { + assert_debug_snapshot!( + do_postfix_completion( + r#" + fn main() { + 42.<|> + } + "#, + ), + @r###"[ + CompletionItem { + label: "box", + source_range: [52; 52), + delete: [49; 52), + insert: "Box::new(42)", + detail: "Box::new(expr)", + }, + CompletionItem { + label: "dbg", + source_range: [52; 52), + delete: [49; 52), + insert: "dbg!(42)", + detail: "dbg!(expr)", + }, + CompletionItem { + label: "match", + source_range: [52; 52), + delete: [49; 52), + insert: "match 42 {\n ${1:_} => {$0\\},\n}", + detail: "match expr {}", + }, + CompletionItem { + label: "not", + source_range: [52; 52), + delete: [49; 52), + insert: "!42", + detail: "!expr", + }, + CompletionItem { + label: "ref", + source_range: [52; 52), + delete: [49; 52), + insert: "&42", + detail: "&expr", + }, + CompletionItem { + label: "refm", + source_range: [52; 52), + delete: [49; 52), + insert: "&mut 42", + detail: "&mut expr", + }, ]"### ); } 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> { pub(super) is_new_item: bool, /// The receiver if this is a field or method access, i.e. writing something.<|> pub(super) dot_receiver: Option, + pub(super) dot_receiver_is_ambiguous_float_literal: bool, /// If this is a call (method or function) in particular, i.e. the () are already there. pub(super) is_call: bool, pub(super) is_path_type: bool, @@ -80,6 +81,7 @@ impl<'a> CompletionContext<'a> { is_call: false, is_path_type: false, has_type_args: false, + dot_receiver_is_ambiguous_float_literal: false, }; ctx.fill(&original_parse, position.offset); Some(ctx) @@ -235,6 +237,16 @@ impl<'a> CompletionContext<'a> { .expr() .map(|e| e.syntax().text_range()) .and_then(|r| find_node_with_range(original_file.syntax(), r)); + self.dot_receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = + &self.dot_receiver + { + match l.kind() { + ast::LiteralKind::FloatNumber { suffix: _ } => l.token().text().ends_with('.'), + _ => false, + } + } else { + false + } } if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { // As above -- cgit v1.2.3