Skip to content

Refactor completion sorting #4114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions crates/ra_ide/src/call_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,24 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
call_info_for_token(&sema, token)
}

pub(crate) fn call_info_for_token(
sema: &Semantics<RootDatabase>,
token: SyntaxToken,
) -> Option<CallInfo> {
#[derive(Debug)]
pub(crate) struct ActiveParameter {
/// FIXME: should be `Type` and `Name
pub(crate) ty: String,
pub(crate) name: String,
}

impl ActiveParameter {
pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> {
call_info(db, position)?.into_active_parameter()
}

pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
call_info_for_token(sema, token)?.into_active_parameter()
}
}

fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<CallInfo> {
// Find the calling expression and it's NameRef
let calling_node = FnCallNode::with_node(&token.parent())?;

Expand Down Expand Up @@ -160,6 +174,14 @@ impl FnCallNode {
}

impl CallInfo {
fn into_active_parameter(self) -> Option<ActiveParameter> {
let idx = self.active_parameter?;
let ty = self.signature.parameter_types.get(idx)?.clone();
let name = self.signature.parameter_names.get(idx)?.clone();
let res = ActiveParameter { ty, name };
Some(res)
}

fn with_fn(db: &RootDatabase, function: hir::Function) -> Self {
let signature = FunctionSignature::from_hir(db, function);

Expand Down
231 changes: 0 additions & 231 deletions crates/ra_ide/src/completion/complete_dot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,237 +105,6 @@ mod tests {
);
}

#[test]
fn test_struct_field_completion_in_func_call() {
assert_debug_snapshot!(
do_ref_completion(
r"
struct A { another_field: i64, the_field: u32, my_string: String }
fn test(my_param: u32) -> u32 { my_param }
fn foo(a: A) {
test(a.<|>)
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: [201; 201),
delete: [201; 201),
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "my_string",
source_range: [201; 201),
delete: [201; 201),
insert: "my_string",
kind: Field,
detail: "{unknown}",
},
CompletionItem {
label: "the_field",
source_range: [201; 201),
delete: [201; 201),
insert: "the_field",
kind: Field,
detail: "u32",
score: TypeMatch,
},
]
"###
);
}

#[test]
fn test_struct_field_completion_in_func_call_with_type_and_name() {
assert_debug_snapshot!(
do_ref_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
fn test(the_field: u32) -> u32 { the_field }
fn foo(a: A) {
test(a.<|>)
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: [208; 208),
delete: [208; 208),
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: [208; 208),
delete: [208; 208),
insert: "another_good_type",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: [208; 208),
delete: [208; 208),
insert: "the_field",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
]
"###
);
}

#[test]
fn test_struct_field_completion_in_record_lit() {
assert_debug_snapshot!(
do_ref_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn foo(a: A) {
let b = B {
the_field: a.<|>
};
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: [270; 270),
delete: [270; 270),
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: [270; 270),
delete: [270; 270),
insert: "another_good_type",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: [270; 270),
delete: [270; 270),
insert: "the_field",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
]
"###
);
}

#[test]
fn test_struct_field_completion_in_record_lit_and_fn_call() {
assert_debug_snapshot!(
do_ref_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn test(the_field: i64) -> i64 { the_field }
fn foo(a: A) {
let b = B {
the_field: test(a.<|>)
};
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: [336; 336),
delete: [336; 336),
insert: "another_field",
kind: Field,
detail: "i64",
score: TypeMatch,
},
CompletionItem {
label: "another_good_type",
source_range: [336; 336),
delete: [336; 336),
insert: "another_good_type",
kind: Field,
detail: "u32",
},
CompletionItem {
label: "the_field",
source_range: [336; 336),
delete: [336; 336),
insert: "the_field",
kind: Field,
detail: "u32",
},
]
"###
);
}

#[test]
fn test_struct_field_completion_in_fn_call_and_record_lit() {
assert_debug_snapshot!(
do_ref_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn test(the_field: i64) -> i64 { the_field }
fn foo(a: A) {
test(B {
the_field: a.<|>
});
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: [328; 328),
delete: [328; 328),
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: [328; 328),
delete: [328; 328),
insert: "another_good_type",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: [328; 328),
delete: [328; 328),
insert: "the_field",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
]
"###
);
}

#[test]
fn test_struct_field_completion_self() {
assert_debug_snapshot!(
Expand Down
7 changes: 4 additions & 3 deletions crates/ra_ide/src/completion/completion_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use ra_syntax::{
};
use ra_text_edit::AtomTextEdit;

use crate::{completion::CompletionConfig, FilePosition};
use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};

/// `CompletionContext` is created early during completion to figure out, where
/// exactly is the cursor, syntax-wise.
Expand All @@ -21,7 +21,6 @@ pub(crate) struct CompletionContext<'a> {
pub(super) db: &'a RootDatabase,
pub(super) config: &'a CompletionConfig,
pub(super) offset: TextUnit,
pub(super) file_position: FilePosition,
/// The token before the cursor, in the original file.
pub(super) original_token: SyntaxToken,
/// The token before the cursor, in the macro-expanded file.
Expand All @@ -34,6 +33,8 @@ pub(crate) struct CompletionContext<'a> {
pub(super) record_pat_syntax: Option<ast::RecordPat>,
pub(super) record_field_syntax: Option<ast::RecordField>,
pub(super) impl_def: Option<ast::ImplDef>,
/// FIXME: `ActiveParameter` is string-based, which is very wrong
pub(super) active_parameter: Option<ActiveParameter>,
pub(super) is_param: bool,
/// If a name-binding or reference to a const in a pattern.
/// Irrefutable patterns (like let) are excluded.
Expand Down Expand Up @@ -90,7 +91,6 @@ impl<'a> CompletionContext<'a> {
original_token,
token,
offset: position.offset,
file_position: position,
krate,
name_ref_syntax: None,
function_syntax: None,
Expand All @@ -99,6 +99,7 @@ impl<'a> CompletionContext<'a> {
record_pat_syntax: None,
record_field_syntax: None,
impl_def: None,
active_parameter: ActiveParameter::at(db, position),
is_param: false,
is_pat_binding_or_const: false,
is_trivial_path: false,
Expand Down
27 changes: 11 additions & 16 deletions crates/ra_ide/src/completion/completion_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub struct CompletionItem {
/// after completion.
trigger_call_info: bool,

/// Score is usefull to pre select or display in better order completion items
/// Score is useful to pre select or display in better order completion items
score: Option<CompletionScore>,
}

Expand Down Expand Up @@ -93,6 +93,14 @@ impl fmt::Debug for CompletionItem {
}
}

#[derive(Debug, Clone, Copy)]
pub enum CompletionScore {
/// If only type match
TypeMatch,
/// If type and name match
TypeAndNameMatch,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompletionItemKind {
Snippet,
Expand Down Expand Up @@ -182,7 +190,7 @@ impl CompletionItem {
}
/// What string is used for filtering.
pub fn lookup(&self) -> &str {
self.lookup.as_deref().unwrap_or_else(|| self.label())
self.lookup.as_deref().unwrap_or(&self.label)
}

pub fn kind(&self) -> Option<CompletionItemKind> {
Expand All @@ -194,11 +202,7 @@ impl CompletionItem {
}

pub fn score(&self) -> Option<CompletionScore> {
self.score.clone()
}

pub fn set_score(&mut self, score: CompletionScore) {
self.score = Some(score);
self.score
}

pub fn trigger_call_info(&self) -> bool {
Expand Down Expand Up @@ -302,7 +306,6 @@ impl Builder {
self.deprecated = Some(deprecated);
self
}
#[allow(unused)]
pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder {
self.score = Some(score);
self
Expand All @@ -319,14 +322,6 @@ impl<'a> Into<CompletionItem> for Builder {
}
}

#[derive(Debug, Clone)]
pub enum CompletionScore {
/// If only type match
TypeMatch,
/// If type and name match
TypeAndNameMatch,
}

/// Represents an in-progress set of completions being built.
#[derive(Debug, Default)]
pub(crate) struct Completions {
Expand Down
Loading