mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Auto merge of #12204 - Veykril:completions, r=Veykril
internal: Move keyword expressions to expr completions module
This commit is contained in:
commit
254bfdd2c3
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use hir::ScopeDef;
|
use hir::ScopeDef;
|
||||||
use ide_db::FxHashSet;
|
use ide_db::FxHashSet;
|
||||||
|
use syntax::T;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
|
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||||
@ -14,15 +15,16 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (&is_absolute_path, qualifier) = match ctx.path_context() {
|
let (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update) =
|
||||||
Some(PathCompletionCtx {
|
match ctx.path_context() {
|
||||||
kind: PathKind::Expr { .. },
|
Some(&PathCompletionCtx {
|
||||||
is_absolute_path,
|
kind: PathKind::Expr { in_block_expr, in_loop_body, in_functional_update },
|
||||||
qualifier,
|
is_absolute_path,
|
||||||
..
|
ref qualifier,
|
||||||
}) => (is_absolute_path, qualifier),
|
..
|
||||||
_ => return,
|
}) => (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update),
|
||||||
};
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let scope_def_applicable = |def| {
|
let scope_def_applicable = |def| {
|
||||||
use hir::{GenericParam::*, ModuleDef::*};
|
use hir::{GenericParam::*, ModuleDef::*};
|
||||||
@ -162,6 +164,64 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
|
|||||||
acc.add_resolution(ctx, name, def);
|
acc.add_resolution(ctx, name, def);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if !in_functional_update {
|
||||||
|
let mut add_keyword =
|
||||||
|
|kw, snippet| super::keyword::add_keyword(acc, ctx, kw, snippet);
|
||||||
|
|
||||||
|
if ctx.expects_expression() {
|
||||||
|
if !in_block_expr {
|
||||||
|
add_keyword("unsafe", "unsafe {\n $0\n}");
|
||||||
|
}
|
||||||
|
add_keyword("match", "match $1 {\n $0\n}");
|
||||||
|
add_keyword("while", "while $1 {\n $0\n}");
|
||||||
|
add_keyword("while let", "while let $1 = $2 {\n $0\n}");
|
||||||
|
add_keyword("loop", "loop {\n $0\n}");
|
||||||
|
add_keyword("if", "if $1 {\n $0\n}");
|
||||||
|
add_keyword("if let", "if let $1 = $2 {\n $0\n}");
|
||||||
|
add_keyword("for", "for $1 in $2 {\n $0\n}");
|
||||||
|
add_keyword("true", "true");
|
||||||
|
add_keyword("false", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.previous_token_is(T![if])
|
||||||
|
|| ctx.previous_token_is(T![while])
|
||||||
|
|| in_block_expr
|
||||||
|
{
|
||||||
|
add_keyword("let", "let");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.after_if() {
|
||||||
|
add_keyword("else", "else {\n $0\n}");
|
||||||
|
add_keyword("else if", "else if $1 {\n $0\n}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.expects_ident_ref_expr() {
|
||||||
|
add_keyword("mut", "mut ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if in_loop_body {
|
||||||
|
if in_block_expr {
|
||||||
|
add_keyword("continue", "continue;");
|
||||||
|
add_keyword("break", "break;");
|
||||||
|
} else {
|
||||||
|
add_keyword("continue", "continue");
|
||||||
|
add_keyword("break", "break");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(fn_def) = &ctx.function_def {
|
||||||
|
add_keyword(
|
||||||
|
"return",
|
||||||
|
match (in_block_expr, fn_def.ret_type().is_some()) {
|
||||||
|
(true, true) => "return ;",
|
||||||
|
(true, false) => "return;",
|
||||||
|
(false, true) => "return $0",
|
||||||
|
(false, false) => "return",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use crate::{
|
|||||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: Make this a submodule of [`pattern`]
|
||||||
/// Complete repeated parameters, both name and type. For example, if all
|
/// Complete repeated parameters, both name and type. For example, if all
|
||||||
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
||||||
/// `spam: &mut Spam` insert text/label will be suggested.
|
/// `spam: &mut Spam` insert text/label will be suggested.
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
use syntax::T;
|
use syntax::T;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{PathCompletionCtx, PathKind},
|
context::PathKind, patterns::ImmediateLocation, CompletionContext, CompletionItem,
|
||||||
patterns::ImmediateLocation,
|
CompletionItemKind, Completions,
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
@ -83,75 +82,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
|||||||
add_keyword("struct", "struct $0");
|
add_keyword("struct", "struct $0");
|
||||||
add_keyword("union", "union $1 {\n $0\n}");
|
add_keyword("union", "union $1 {\n $0\n}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.expects_type() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.expects_expression() {
|
|
||||||
if !has_block_expr_parent {
|
|
||||||
add_keyword("unsafe", "unsafe {\n $0\n}");
|
|
||||||
}
|
|
||||||
add_keyword("match", "match $1 {\n $0\n}");
|
|
||||||
add_keyword("while", "while $1 {\n $0\n}");
|
|
||||||
add_keyword("while let", "while let $1 = $2 {\n $0\n}");
|
|
||||||
add_keyword("loop", "loop {\n $0\n}");
|
|
||||||
add_keyword("if", "if $1 {\n $0\n}");
|
|
||||||
add_keyword("if let", "if let $1 = $2 {\n $0\n}");
|
|
||||||
add_keyword("for", "for $1 in $2 {\n $0\n}");
|
|
||||||
add_keyword("true", "true");
|
|
||||||
add_keyword("false", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
|
|
||||||
add_keyword("let", "let");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.after_if() {
|
|
||||||
add_keyword("else", "else {\n $0\n}");
|
|
||||||
add_keyword("else if", "else if $1 {\n $0\n}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.expects_ident_ref_expr() {
|
|
||||||
add_keyword("mut", "mut ");
|
|
||||||
}
|
|
||||||
|
|
||||||
let (can_be_stmt, in_loop_body) = match ctx.path_context() {
|
|
||||||
Some(&PathCompletionCtx {
|
|
||||||
is_absolute_path: false,
|
|
||||||
kind: PathKind::Expr { in_block_expr, in_loop_body, .. },
|
|
||||||
..
|
|
||||||
}) => (in_block_expr, in_loop_body),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
if in_loop_body {
|
|
||||||
if can_be_stmt {
|
|
||||||
add_keyword("continue", "continue;");
|
|
||||||
add_keyword("break", "break;");
|
|
||||||
} else {
|
|
||||||
add_keyword("continue", "continue");
|
|
||||||
add_keyword("break", "break");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fn_def = match &ctx.function_def {
|
|
||||||
Some(it) => it,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
add_keyword(
|
|
||||||
"return",
|
|
||||||
match (can_be_stmt, fn_def.ret_type().is_some()) {
|
|
||||||
(true, true) => "return $0;",
|
|
||||||
(true, false) => "return;",
|
|
||||||
(false, true) => "return $0",
|
|
||||||
(false, false) => "return",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
|
pub(super) fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
|
||||||
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
|
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
|
||||||
|
|
||||||
match ctx.config.snippet_cap {
|
match ctx.config.snippet_cap {
|
||||||
|
@ -52,6 +52,7 @@ enum ImplCompletionKind {
|
|||||||
Const,
|
Const,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Make this a submodule of [`item_list`]
|
||||||
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if let Some((kind, replacement_range, impl_def)) = completion_match(ctx) {
|
if let Some((kind, replacement_range, impl_def)) = completion_match(ctx) {
|
||||||
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
|
if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Completions,
|
Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
let (&is_absolute_path, qualifier, &has_in_token) = match ctx.path_context() {
|
let (&is_absolute_path, qualifier, &has_in_token) = match ctx.path_context() {
|
||||||
Some(PathCompletionCtx {
|
Some(PathCompletionCtx {
|
||||||
kind: PathKind::Vis { has_in_token },
|
kind: PathKind::Vis { has_in_token },
|
||||||
|
@ -48,6 +48,7 @@ pub(super) enum PathKind {
|
|||||||
Expr {
|
Expr {
|
||||||
in_block_expr: bool,
|
in_block_expr: bool,
|
||||||
in_loop_body: bool,
|
in_loop_body: bool,
|
||||||
|
in_functional_update: bool,
|
||||||
},
|
},
|
||||||
Type,
|
Type,
|
||||||
Attr {
|
Attr {
|
||||||
@ -392,10 +393,6 @@ impl<'a> CompletionContext<'a> {
|
|||||||
matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Expr { .. }, .. }))
|
matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Expr { .. }, .. }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expects_type(&self) -> bool {
|
|
||||||
matches!(self.path_context(), Some(PathCompletionCtx { kind: PathKind::Type, .. }))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_non_trivial_path(&self) -> bool {
|
pub(crate) fn is_non_trivial_path(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self.path_context(),
|
self.path_context(),
|
||||||
@ -1104,6 +1101,9 @@ impl<'a> CompletionContext<'a> {
|
|||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
};
|
};
|
||||||
|
let is_in_func_update = |it: &SyntaxNode| {
|
||||||
|
it.parent().map_or(false, |it| ast::RecordExprFieldList::can_cast(it.kind()))
|
||||||
|
};
|
||||||
|
|
||||||
let kind = path.syntax().ancestors().find_map(|it| {
|
let kind = path.syntax().ancestors().find_map(|it| {
|
||||||
// using Option<Option<PathKind>> as extra controlflow
|
// using Option<Option<PathKind>> as extra controlflow
|
||||||
@ -1114,8 +1114,8 @@ impl<'a> CompletionContext<'a> {
|
|||||||
path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
|
path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
|
||||||
let in_block_expr = is_in_block(it.syntax());
|
let in_block_expr = is_in_block(it.syntax());
|
||||||
let in_loop_body = is_in_loop_body(it.syntax());
|
let in_loop_body = is_in_loop_body(it.syntax());
|
||||||
|
let in_functional_update = is_in_func_update(it.syntax());
|
||||||
Some(PathKind::Expr { in_block_expr, in_loop_body })
|
Some(PathKind::Expr { in_block_expr, in_loop_body, in_functional_update })
|
||||||
},
|
},
|
||||||
ast::TupleStructPat(it) => {
|
ast::TupleStructPat(it) => {
|
||||||
path_ctx.has_call_parens = true;
|
path_ctx.has_call_parens = true;
|
||||||
@ -1149,7 +1149,8 @@ impl<'a> CompletionContext<'a> {
|
|||||||
return Some(parent.and_then(ast::MacroExpr::cast).map(|it| {
|
return Some(parent.and_then(ast::MacroExpr::cast).map(|it| {
|
||||||
let in_loop_body = is_in_loop_body(it.syntax());
|
let in_loop_body = is_in_loop_body(it.syntax());
|
||||||
let in_block_expr = is_in_block(it.syntax());
|
let in_block_expr = is_in_block(it.syntax());
|
||||||
PathKind::Expr { in_block_expr, in_loop_body }
|
let in_functional_update = is_in_func_update(it.syntax());
|
||||||
|
PathKind::Expr { in_block_expr, in_loop_body, in_functional_update }
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ pub fn completions(
|
|||||||
completions::r#type::complete_type_path(acc, ctx);
|
completions::r#type::complete_type_path(acc, ctx);
|
||||||
completions::r#type::complete_inferred_type(acc, ctx);
|
completions::r#type::complete_inferred_type(acc, ctx);
|
||||||
completions::use_::complete_use_tree(acc, ctx);
|
completions::use_::complete_use_tree(acc, ctx);
|
||||||
completions::vis::complete_vis(acc, ctx);
|
completions::vis::complete_vis_path(acc, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(acc)
|
Some(acc)
|
||||||
|
@ -168,19 +168,8 @@ fn main() {
|
|||||||
tt Sized
|
tt Sized
|
||||||
bt u32
|
bt u32
|
||||||
kw crate::
|
kw crate::
|
||||||
kw false
|
|
||||||
kw for
|
|
||||||
kw if
|
|
||||||
kw if let
|
|
||||||
kw loop
|
|
||||||
kw match
|
|
||||||
kw return
|
|
||||||
kw self::
|
kw self::
|
||||||
kw super::
|
kw super::
|
||||||
kw true
|
|
||||||
kw unsafe
|
|
||||||
kw while
|
|
||||||
kw while let
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
|
Loading…
Reference in New Issue
Block a user