mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-11 20:58:54 +00:00
Cleanup auto-ref in completion
This commit is contained in:
parent
abc0ed36bd
commit
12fe301a0c
4 changed files with 87 additions and 30 deletions
|
@ -1614,10 +1614,9 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_ref(&self) -> Option<Type> {
|
pub fn remove_ref(&self) -> Option<Type> {
|
||||||
if let Ty::Ref(.., substs) = &self.ty.value {
|
match &self.ty.value {
|
||||||
Some(self.derived(substs[0].clone()))
|
Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())),
|
||||||
} else {
|
_ => None,
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub struct CompletionItem {
|
||||||
|
|
||||||
/// Indicates that a reference or mutable reference to this variable is a
|
/// Indicates that a reference or mutable reference to this variable is a
|
||||||
/// possible match.
|
/// possible match.
|
||||||
ref_match: Option<(Mutability, CompletionScore)>,
|
ref_match: Option<Mutability>,
|
||||||
|
|
||||||
/// The import data to add to completion's edits.
|
/// The import data to add to completion's edits.
|
||||||
import_to_add: Option<ImportEdit>,
|
import_to_add: Option<ImportEdit>,
|
||||||
|
@ -104,6 +104,9 @@ impl fmt::Debug for CompletionItem {
|
||||||
if let Some(score) = &self.score {
|
if let Some(score) = &self.score {
|
||||||
s.field("score", score);
|
s.field("score", score);
|
||||||
}
|
}
|
||||||
|
if let Some(mutability) = &self.ref_match {
|
||||||
|
s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref()));
|
||||||
|
}
|
||||||
if self.trigger_call_info {
|
if self.trigger_call_info {
|
||||||
s.field("trigger_call_info", &true);
|
s.field("trigger_call_info", &true);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +264,7 @@ impl CompletionItem {
|
||||||
self.trigger_call_info
|
self.trigger_call_info
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ref_match(&self) -> Option<(Mutability, CompletionScore)> {
|
pub fn ref_match(&self) -> Option<Mutability> {
|
||||||
self.ref_match
|
self.ref_match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +314,7 @@ pub(crate) struct Builder {
|
||||||
deprecated: bool,
|
deprecated: bool,
|
||||||
trigger_call_info: Option<bool>,
|
trigger_call_info: Option<bool>,
|
||||||
score: Option<CompletionScore>,
|
score: Option<CompletionScore>,
|
||||||
ref_match: Option<(Mutability, CompletionScore)>,
|
ref_match: Option<Mutability>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
|
@ -430,8 +433,8 @@ impl Builder {
|
||||||
self.import_to_add = import_to_add;
|
self.import_to_add = import_to_add;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub(crate) fn ref_match(mut self, ref_match: (Mutability, CompletionScore)) -> Builder {
|
pub(crate) fn ref_match(mut self, mutability: Mutability) -> Builder {
|
||||||
self.ref_match = Some(ref_match);
|
self.ref_match = Some(mutability);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,10 +254,17 @@ impl<'a> Render<'a> {
|
||||||
{
|
{
|
||||||
item = item.set_score(score);
|
item = item.set_score(score);
|
||||||
}
|
}
|
||||||
if let Some(ref_match) =
|
|
||||||
refed_type_matches(&active_type, &active_name, &ty, &local_name)
|
if let Some(ty_without_ref) = active_type.remove_ref() {
|
||||||
{
|
if ty_without_ref == ty {
|
||||||
item = item.ref_match(ref_match);
|
cov_mark::hit!(suggest_ref);
|
||||||
|
let mutability = if active_type.is_mutable_reference() {
|
||||||
|
Mutability::Mut
|
||||||
|
} else {
|
||||||
|
Mutability::Shared
|
||||||
|
};
|
||||||
|
item = item.ref_match(mutability)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,19 +347,6 @@ fn compute_score_from_active(
|
||||||
|
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
fn refed_type_matches(
|
|
||||||
active_type: &Type,
|
|
||||||
active_name: &str,
|
|
||||||
ty: &Type,
|
|
||||||
name: &str,
|
|
||||||
) -> Option<(Mutability, CompletionScore)> {
|
|
||||||
let derefed_active = active_type.remove_ref()?;
|
|
||||||
let score = compute_score_from_active(&derefed_active, &active_name, &ty, &name)?;
|
|
||||||
Some((
|
|
||||||
if active_type.is_mutable_reference() { Mutability::Mut } else { Mutability::Shared },
|
|
||||||
score,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_score(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionScore> {
|
fn compute_score(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionScore> {
|
||||||
let (active_name, active_type) = ctx.active_name_and_type()?;
|
let (active_name, active_type) = ctx.active_name_and_type()?;
|
||||||
|
@ -947,4 +941,66 @@ fn f(foo: &Foo) { f(foo, w$0) }
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn suggest_ref_mut() {
|
||||||
|
cov_mark::check!(suggest_ref);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct S;
|
||||||
|
fn foo(s: &mut S) {}
|
||||||
|
fn main() {
|
||||||
|
let mut s = S;
|
||||||
|
foo($0);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
[
|
||||||
|
CompletionItem {
|
||||||
|
label: "S",
|
||||||
|
source_range: 70..70,
|
||||||
|
delete: 70..70,
|
||||||
|
insert: "S",
|
||||||
|
kind: SymbolKind(
|
||||||
|
Struct,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "foo(…)",
|
||||||
|
source_range: 70..70,
|
||||||
|
delete: 70..70,
|
||||||
|
insert: "foo(${1:&mut s})$0",
|
||||||
|
kind: SymbolKind(
|
||||||
|
Function,
|
||||||
|
),
|
||||||
|
lookup: "foo",
|
||||||
|
detail: "-> ()",
|
||||||
|
trigger_call_info: true,
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "main()",
|
||||||
|
source_range: 70..70,
|
||||||
|
delete: 70..70,
|
||||||
|
insert: "main()$0",
|
||||||
|
kind: SymbolKind(
|
||||||
|
Function,
|
||||||
|
),
|
||||||
|
lookup: "main",
|
||||||
|
detail: "-> ()",
|
||||||
|
},
|
||||||
|
CompletionItem {
|
||||||
|
label: "s",
|
||||||
|
source_range: 70..70,
|
||||||
|
delete: 70..70,
|
||||||
|
insert: "s",
|
||||||
|
kind: SymbolKind(
|
||||||
|
Local,
|
||||||
|
),
|
||||||
|
detail: "S",
|
||||||
|
ref_match: "&mut ",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,9 +232,8 @@ pub(crate) fn completion_item(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut res = match item.ref_match() {
|
let mut res = match item.ref_match() {
|
||||||
Some(ref_match) => {
|
Some(mutability) => {
|
||||||
let mut refed = lsp_item.clone();
|
let mut refed = lsp_item.clone();
|
||||||
let (mutability, _score) = ref_match;
|
|
||||||
let label = format!("&{}{}", mutability.as_keyword_for_ref(), refed.label);
|
let label = format!("&{}{}", mutability.as_keyword_for_ref(), refed.label);
|
||||||
set_score(&mut refed, &label);
|
set_score(&mut refed, &label);
|
||||||
refed.label = label;
|
refed.label = label;
|
||||||
|
@ -243,8 +242,8 @@ pub(crate) fn completion_item(
|
||||||
None => vec![lsp_item],
|
None => vec![lsp_item],
|
||||||
};
|
};
|
||||||
|
|
||||||
for mut r in res.iter_mut() {
|
for lsp_item in res.iter_mut() {
|
||||||
r.insert_text_format = Some(insert_text_format(item.insert_text_format()));
|
lsp_item.insert_text_format = Some(insert_text_format(item.insert_text_format()));
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue