mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Simplify
This commit is contained in:
parent
06b0cbf607
commit
3956a5b757
9 changed files with 91 additions and 51 deletions
|
@ -1,4 +1,6 @@
|
||||||
//! Completes keywords.
|
//! Completes keywords, except:
|
||||||
|
//! - `self`, `super` and `crate`, as these are considered part of path completions.
|
||||||
|
//! - `await`, as this is a postfix completion we handle this in the postfix completions.
|
||||||
|
|
||||||
use syntax::{SyntaxKind, T};
|
use syntax::{SyntaxKind, T};
|
||||||
|
|
||||||
|
@ -25,18 +27,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suggest .await syntax for types that implement Future trait
|
|
||||||
if let Some(receiver) = ctx.dot_receiver() {
|
|
||||||
if let Some(ty) = ctx.sema.type_of_expr(receiver) {
|
|
||||||
if ty.impls_future(ctx.db) {
|
|
||||||
let mut item =
|
|
||||||
CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
|
|
||||||
item.kind(CompletionItemKind::Keyword).detail("expr.await");
|
|
||||||
item.add_to(acc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
|
let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
|
||||||
|
|
||||||
let expects_assoc_item = ctx.expects_assoc_item();
|
let expects_assoc_item = ctx.expects_assoc_item();
|
||||||
|
|
|
@ -42,6 +42,13 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Suggest .await syntax for types that implement Future trait
|
||||||
|
if receiver_ty.impls_future(ctx.db) {
|
||||||
|
let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
|
||||||
|
item.kind(CompletionItemKind::Keyword).detail("expr.await");
|
||||||
|
item.add_to(acc);
|
||||||
|
}
|
||||||
|
|
||||||
let cap = match ctx.config.snippet_cap {
|
let cap = match ctx.config.snippet_cap {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return,
|
None => return,
|
||||||
|
|
|
@ -6,10 +6,12 @@ use hir::HasVisibility;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
|
|
||||||
use crate::{context::PathCompletionContext, CompletionContext, Completions};
|
use crate::{
|
||||||
|
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, Completions,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if ctx.is_path_disallowed() {
|
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (path, use_tree_parent) = match &ctx.path_context {
|
let (path, use_tree_parent) = match &ctx.path_context {
|
||||||
|
@ -26,10 +28,11 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||||
|
|
||||||
let context_module = ctx.scope.module();
|
let context_module = ctx.scope.module();
|
||||||
|
|
||||||
if ctx.expects_item() || ctx.expects_assoc_item() {
|
if let Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) =
|
||||||
|
ctx.completion_location
|
||||||
|
{
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||||
let module_scope = module.scope(ctx.db, context_module);
|
for (name, def) in module.scope(ctx.db, context_module) {
|
||||||
for (name, def) in module_scope {
|
|
||||||
if let hir::ScopeDef::MacroDef(macro_def) = def {
|
if let hir::ScopeDef::MacroDef(macro_def) = def {
|
||||||
if macro_def.is_fn_like() {
|
if macro_def.is_fn_like() {
|
||||||
acc.add_macro(ctx, Some(name.clone()), macro_def);
|
acc.add_macro(ctx, Some(name.clone()), macro_def);
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
|
|
||||||
if ctx.in_use_tree() {
|
if ctx.in_use_tree() {
|
||||||
// only show modules in a fresh UseTree
|
// only show modules in a fresh UseTree
|
||||||
cov_mark::hit!(only_completes_modules_in_import);
|
cov_mark::hit!(unqualified_path_only_modules_in_import);
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||||
acc.add_resolution(ctx, name, &res);
|
acc.add_resolution(ctx, name, &res);
|
||||||
|
@ -24,37 +24,39 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
|
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
|
||||||
if let Some(ImmediateLocation::Visibility(_)) = ctx.completion_location {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.expects_item() || ctx.expects_assoc_item() {
|
match &ctx.completion_location {
|
||||||
// only show macros in {Assoc}ItemList
|
Some(ImmediateLocation::Visibility(_)) => return,
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||||
if let hir::ScopeDef::MacroDef(mac) = res {
|
// only show macros in {Assoc}ItemList
|
||||||
if mac.is_fn_like() {
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
acc.add_macro(ctx, Some(name.clone()), mac);
|
if let hir::ScopeDef::MacroDef(mac) = res {
|
||||||
|
if mac.is_fn_like() {
|
||||||
|
acc.add_macro(ctx, Some(name.clone()), mac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
||||||
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
|
acc.add_resolution(ctx, name, &res);
|
||||||
acc.add_resolution(ctx, name, &res);
|
}
|
||||||
}
|
});
|
||||||
});
|
return;
|
||||||
return;
|
}
|
||||||
}
|
Some(ImmediateLocation::TypeBound) => {
|
||||||
|
ctx.scope.process_all_names(&mut |name, res| {
|
||||||
if matches!(&ctx.completion_location, Some(ImmediateLocation::TypeBound)) {
|
let add_resolution = match res {
|
||||||
ctx.scope.process_all_names(&mut |name, res| {
|
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
||||||
let add_resolution = match res {
|
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => {
|
||||||
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
true
|
||||||
ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => true,
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if add_resolution {
|
if add_resolution {
|
||||||
acc.add_resolution(ctx, name, &res);
|
acc.add_resolution(ctx, name, &res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.expects_type() {
|
if !ctx.expects_type() {
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
//! Patterns telling us certain facts about current syntax element, they are used in completion context
|
//! Patterns telling us certain facts about current syntax element, they are used in completion context
|
||||||
|
//!
|
||||||
|
//! Most logic in this module first expands the token below the cursor to a maximum node that acts similar to the token itself.
|
||||||
|
//! This means we for example expand a NameRef token to its outermost Path node, as semantically these act in the same location
|
||||||
|
//! and the completions usually query for path specific things on the Path context instead. This simplifies some location handling.
|
||||||
|
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
|
|
|
@ -201,7 +201,7 @@ pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElemen
|
||||||
|
|
||||||
pub(crate) fn get_all_items(config: CompletionConfig, code: &str) -> Vec<CompletionItem> {
|
pub(crate) fn get_all_items(config: CompletionConfig, code: &str) -> Vec<CompletionItem> {
|
||||||
let (db, position) = position(code);
|
let (db, position) = position(code);
|
||||||
crate::completions(&db, &config, position).unwrap().into()
|
crate::completions(&db, &config, position).map_or_else(Vec::default, Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_no_completion(ra_fixture: &str) {
|
fn check_no_completion(ra_fixture: &str) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ fn after_trait_name_in_trait_def() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn after_trait_or_target_name_in_impl() {
|
fn after_target_name_in_impl() {
|
||||||
check(
|
check(
|
||||||
r"impl Trait $0",
|
r"impl Trait $0",
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
|
@ -76,6 +76,8 @@ fn after_trait_or_target_name_in_impl() {
|
||||||
kw for
|
kw for
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
// FIXME: This should emit `kw where`
|
||||||
|
check(r"impl Trait for Type $0", expect![[r#""#]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -10,7 +10,7 @@ fn check(ra_fixture: &str, expect: Expect) {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn use_tree_start() {
|
fn use_tree_start() {
|
||||||
cov_mark::check!(only_completes_modules_in_import);
|
cov_mark::check!(unqualified_path_only_modules_in_import);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- /lib.rs crate:main deps:other_crate
|
//- /lib.rs crate:main deps:other_crate
|
||||||
|
|
|
@ -23,3 +23,35 @@ pub($0)
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn after_in_kw() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
pub(in $0)
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
kw self
|
||||||
|
kw super
|
||||||
|
kw crate
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn qualified() {
|
||||||
|
// FIXME: only show parent modules
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
mod foo {
|
||||||
|
pub(in crate::$0)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod bar {}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
md bar
|
||||||
|
md foo
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue