mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
#1435 postfix completion for integer literals
This commit is contained in:
parent
77f2dd96a1
commit
bec47e221f
2 changed files with 77 additions and 2 deletions
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
CompletionItem,
|
CompletionItem,
|
||||||
};
|
};
|
||||||
use hir::{Ty, TypeCtor};
|
use hir::{Ty, TypeCtor};
|
||||||
use ra_syntax::{ast::AstNode, TextRange};
|
use ra_syntax::{ast::AstNode, TextRange, TextUnit};
|
||||||
use ra_text_edit::TextEditBuilder;
|
use ra_text_edit::TextEditBuilder;
|
||||||
|
|
||||||
fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
|
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 {
|
||||||
|
|
||||||
pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if let Some(dot_receiver) = &ctx.dot_receiver {
|
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);
|
let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver);
|
||||||
if is_bool_or_unknown(receiver_ty) {
|
if is_bool_or_unknown(receiver_ty) {
|
||||||
postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
|
postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
|
||||||
|
@ -206,6 +212,63 @@ mod tests {
|
||||||
insert: "&mut bar",
|
insert: "&mut bar",
|
||||||
detail: "&mut expr",
|
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",
|
||||||
|
},
|
||||||
]"###
|
]"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
pub(super) is_new_item: bool,
|
pub(super) is_new_item: bool,
|
||||||
/// The receiver if this is a field or method access, i.e. writing something.<|>
|
/// The receiver if this is a field or method access, i.e. writing something.<|>
|
||||||
pub(super) dot_receiver: Option<ast::Expr>,
|
pub(super) dot_receiver: Option<ast::Expr>,
|
||||||
|
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.
|
/// If this is a call (method or function) in particular, i.e. the () are already there.
|
||||||
pub(super) is_call: bool,
|
pub(super) is_call: bool,
|
||||||
pub(super) is_path_type: bool,
|
pub(super) is_path_type: bool,
|
||||||
|
@ -80,6 +81,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
is_call: false,
|
is_call: false,
|
||||||
is_path_type: false,
|
is_path_type: false,
|
||||||
has_type_args: false,
|
has_type_args: false,
|
||||||
|
dot_receiver_is_ambiguous_float_literal: false,
|
||||||
};
|
};
|
||||||
ctx.fill(&original_parse, position.offset);
|
ctx.fill(&original_parse, position.offset);
|
||||||
Some(ctx)
|
Some(ctx)
|
||||||
|
@ -235,6 +237,16 @@ impl<'a> CompletionContext<'a> {
|
||||||
.expr()
|
.expr()
|
||||||
.map(|e| e.syntax().text_range())
|
.map(|e| e.syntax().text_range())
|
||||||
.and_then(|r| find_node_with_range(original_file.syntax(), r));
|
.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) {
|
if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
|
||||||
// As above
|
// As above
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue