mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
Enable qualifier completions for derives
This commit is contained in:
parent
2abe19e46a
commit
b1ab5770c9
2 changed files with 123 additions and 83 deletions
|
@ -1,79 +1,113 @@
|
||||||
//! Completion for derives
|
//! Completion for derives
|
||||||
use hir::{HasAttrs, Macro};
|
use hir::{HasAttrs, ScopeDef};
|
||||||
use ide_db::SymbolKind;
|
use ide_db::SymbolKind;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{CompletionContext, PathCompletionCtx, PathKind},
|
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||||
item::CompletionItem,
|
item::CompletionItem,
|
||||||
Completions,
|
Completions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
match ctx.path_context {
|
let (qualifier, is_absolute_path) = match ctx.path_context {
|
||||||
// FIXME: Enable qualified completions
|
Some(PathCompletionCtx {
|
||||||
Some(PathCompletionCtx { kind: Some(PathKind::Derive), qualifier: None, .. }) => (),
|
kind: Some(PathKind::Derive),
|
||||||
|
ref qualifier,
|
||||||
|
is_absolute_path,
|
||||||
|
..
|
||||||
|
}) => (qualifier, is_absolute_path),
|
||||||
_ => return,
|
_ => return,
|
||||||
}
|
};
|
||||||
|
|
||||||
let core = ctx.famous_defs().core();
|
let core = ctx.famous_defs().core();
|
||||||
|
|
||||||
for (name, mac) in get_derives_in_scope(ctx) {
|
match qualifier {
|
||||||
if ctx.existing_derives.contains(&mac) {
|
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
|
||||||
continue;
|
if *is_super_chain {
|
||||||
}
|
acc.add_keyword(ctx, "super::");
|
||||||
|
}
|
||||||
|
|
||||||
let name = name.to_smol_str();
|
let module = match resolution {
|
||||||
let (label, lookup) = match (core, mac.module(ctx.db).krate()) {
|
Some(hir::PathResolution::Def(hir::ModuleDef::Module(it))) => it,
|
||||||
// show derive dependencies for `core`/`std` derives
|
_ => return,
|
||||||
(Some(core), mac_krate) if core == mac_krate => {
|
};
|
||||||
if let Some(derive_completion) = DEFAULT_DERIVE_DEPENDENCIES
|
|
||||||
.iter()
|
for (name, def) in module.scope(ctx.db, ctx.module) {
|
||||||
.find(|derive_completion| derive_completion.label == name)
|
let add_def = match def {
|
||||||
{
|
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
|
||||||
let mut components = vec![derive_completion.label];
|
!ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db)
|
||||||
components.extend(derive_completion.dependencies.iter().filter(
|
}
|
||||||
|&&dependency| {
|
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
|
||||||
!ctx.existing_derives
|
_ => false,
|
||||||
.iter()
|
};
|
||||||
.map(|it| it.name(ctx.db))
|
if add_def {
|
||||||
.any(|it| it.to_smol_str() == dependency)
|
acc.add_resolution(ctx, name, def);
|
||||||
},
|
|
||||||
));
|
|
||||||
let lookup = components.join(", ");
|
|
||||||
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
|
|
||||||
(SmolStr::from_iter(label), Some(lookup))
|
|
||||||
} else {
|
|
||||||
(name, None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (name, None),
|
return;
|
||||||
};
|
}
|
||||||
|
None if is_absolute_path => acc.add_crate_roots(ctx),
|
||||||
|
// only show modules in a fresh UseTree
|
||||||
|
None => {
|
||||||
|
ctx.process_all_names(&mut |name, def| {
|
||||||
|
let mac = match def {
|
||||||
|
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
|
||||||
|
if !ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
|
||||||
|
{
|
||||||
|
mac
|
||||||
|
}
|
||||||
|
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => {
|
||||||
|
return acc.add_resolution(ctx, name, def);
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let mut item = CompletionItem::new(SymbolKind::Derive, ctx.source_range(), label);
|
match (core, mac.module(ctx.db).krate()) {
|
||||||
if let Some(docs) = mac.docs(ctx.db) {
|
// show derive dependencies for `core`/`std` derives
|
||||||
item.documentation(docs);
|
(Some(core), mac_krate) if core == mac_krate && qualifier.is_none() => {}
|
||||||
|
_ => return acc.add_resolution(ctx, name, def),
|
||||||
|
};
|
||||||
|
|
||||||
|
let name_ = name.to_smol_str();
|
||||||
|
let find = DEFAULT_DERIVE_DEPENDENCIES
|
||||||
|
.iter()
|
||||||
|
.find(|derive_completion| derive_completion.label == name_);
|
||||||
|
|
||||||
|
match find {
|
||||||
|
Some(derive_completion) => {
|
||||||
|
let mut components = vec![derive_completion.label];
|
||||||
|
components.extend(derive_completion.dependencies.iter().filter(
|
||||||
|
|&&dependency| {
|
||||||
|
!ctx.existing_derives
|
||||||
|
.iter()
|
||||||
|
.map(|it| it.name(ctx.db))
|
||||||
|
.any(|it| it.to_smol_str() == dependency)
|
||||||
|
},
|
||||||
|
));
|
||||||
|
let lookup = components.join(", ");
|
||||||
|
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
|
||||||
|
|
||||||
|
let mut item = CompletionItem::new(
|
||||||
|
SymbolKind::Derive,
|
||||||
|
ctx.source_range(),
|
||||||
|
SmolStr::from_iter(label),
|
||||||
|
);
|
||||||
|
if let Some(docs) = mac.docs(ctx.db) {
|
||||||
|
item.documentation(docs);
|
||||||
|
}
|
||||||
|
item.lookup_by(lookup);
|
||||||
|
item.add_to(acc);
|
||||||
|
}
|
||||||
|
None => acc.add_resolution(ctx, name, def),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
acc.add_nameref_keywords(ctx);
|
||||||
}
|
}
|
||||||
if let Some(lookup) = lookup {
|
|
||||||
item.lookup_by(lookup);
|
|
||||||
}
|
|
||||||
item.add_to(acc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, Macro)> {
|
|
||||||
let mut result = Vec::default();
|
|
||||||
ctx.process_all_names(&mut |name, scope_def| {
|
|
||||||
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) = scope_def {
|
|
||||||
if mac.kind(ctx.db) == hir::MacroKind::Derive {
|
|
||||||
result.push((name, mac));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DeriveDependencies {
|
struct DeriveDependencies {
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
dependencies: &'static [&'static str],
|
dependencies: &'static [&'static str],
|
||||||
|
|
|
@ -688,13 +688,17 @@ mod derive {
|
||||||
#[derive($0)] struct Test;
|
#[derive($0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
de Default
|
md core
|
||||||
|
de Default pub macro Default
|
||||||
de Clone, Copy
|
de Clone, Copy
|
||||||
de PartialEq
|
de PartialEq pub macro PartialEq
|
||||||
de PartialEq, Eq
|
de PartialEq, Eq
|
||||||
de PartialEq, Eq, PartialOrd, Ord
|
de PartialEq, Eq, PartialOrd, Ord
|
||||||
de Clone
|
de Clone pub macro Clone
|
||||||
de PartialEq, PartialOrd
|
de PartialEq, PartialOrd
|
||||||
|
kw self::
|
||||||
|
kw super::
|
||||||
|
kw crate::
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -707,12 +711,16 @@ mod derive {
|
||||||
#[derive(serde::Serialize, PartialEq, $0)] struct Test;
|
#[derive(serde::Serialize, PartialEq, $0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
de Default
|
md core
|
||||||
|
de Default pub macro Default
|
||||||
de Clone, Copy
|
de Clone, Copy
|
||||||
de Eq
|
de Eq
|
||||||
de Eq, PartialOrd, Ord
|
de Eq, PartialOrd, Ord
|
||||||
de Clone
|
de Clone pub macro Clone
|
||||||
de PartialOrd
|
de PartialOrd
|
||||||
|
kw self::
|
||||||
|
kw super::
|
||||||
|
kw crate::
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -725,36 +733,20 @@ mod derive {
|
||||||
#[derive($0 serde::Serialize, PartialEq)] struct Test;
|
#[derive($0 serde::Serialize, PartialEq)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
de Default
|
md core
|
||||||
|
de Default pub macro Default
|
||||||
de Clone, Copy
|
de Clone, Copy
|
||||||
de Eq
|
de Eq
|
||||||
de Eq, PartialOrd, Ord
|
de Eq, PartialOrd, Ord
|
||||||
de Clone
|
de Clone pub macro Clone
|
||||||
de PartialOrd
|
de PartialOrd
|
||||||
|
kw self::
|
||||||
|
kw super::
|
||||||
|
kw crate::
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn derive_no_attrs() {
|
|
||||||
check_derive(
|
|
||||||
r#"
|
|
||||||
//- proc_macros: identity
|
|
||||||
//- minicore: derive
|
|
||||||
#[derive($0)] struct Test;
|
|
||||||
"#,
|
|
||||||
expect![[r#""#]],
|
|
||||||
);
|
|
||||||
check_derive(
|
|
||||||
r#"
|
|
||||||
//- proc_macros: identity
|
|
||||||
//- minicore: derive
|
|
||||||
#[derive(i$0)] struct Test;
|
|
||||||
"#,
|
|
||||||
expect![[r#""#]],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn derive_flyimport() {
|
fn derive_flyimport() {
|
||||||
check_derive(
|
check_derive(
|
||||||
|
@ -764,6 +756,11 @@ mod derive {
|
||||||
#[derive(der$0)] struct Test;
|
#[derive(der$0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
|
md proc_macros
|
||||||
|
md core
|
||||||
|
kw self::
|
||||||
|
kw super::
|
||||||
|
kw crate::
|
||||||
de DeriveIdentity (use proc_macros::DeriveIdentity) pub macro derive_identity
|
de DeriveIdentity (use proc_macros::DeriveIdentity) pub macro derive_identity
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -775,7 +772,12 @@ use proc_macros::DeriveIdentity;
|
||||||
#[derive(der$0)] struct Test;
|
#[derive(der$0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
de DeriveIdentity
|
de DeriveIdentity pub macro derive_identity
|
||||||
|
md proc_macros
|
||||||
|
md core
|
||||||
|
kw self::
|
||||||
|
kw super::
|
||||||
|
kw crate::
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -805,7 +807,9 @@ use proc_macros::DeriveIdentity;
|
||||||
//- minicore: derive, copy, clone
|
//- minicore: derive, copy, clone
|
||||||
#[derive(proc_macros::$0)] struct Test;
|
#[derive(proc_macros::$0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#""#]],
|
expect![[r#"
|
||||||
|
de DeriveIdentity pub macro derive_identity
|
||||||
|
"#]],
|
||||||
);
|
);
|
||||||
check_derive(
|
check_derive(
|
||||||
r#"
|
r#"
|
||||||
|
@ -813,7 +817,9 @@ use proc_macros::DeriveIdentity;
|
||||||
//- minicore: derive, copy, clone
|
//- minicore: derive, copy, clone
|
||||||
#[derive(proc_macros::C$0)] struct Test;
|
#[derive(proc_macros::C$0)] struct Test;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#""#]],
|
expect![[r#"
|
||||||
|
de DeriveIdentity pub macro derive_identity
|
||||||
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue