Don't use an untyped String for ActiveParam tracking
This commit is contained in:
parent
5cc8ad0c4a
commit
38048c35d8
@ -23,7 +23,7 @@ pub(super) fn ra_fixture(
|
|||||||
expanded: SyntaxToken,
|
expanded: SyntaxToken,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let active_parameter = ActiveParameter::at_token(&sema, expanded)?;
|
let active_parameter = ActiveParameter::at_token(&sema, expanded)?;
|
||||||
if !active_parameter.name.starts_with("ra_fixture") {
|
if !active_parameter.ident().map_or(false, |name| name.text().starts_with("ra_fixture")) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let value = literal.value()?;
|
let value = literal.value()?;
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
use ide_db::base_db::{FilePosition, SourceDatabase};
|
use ide_db::base_db::{FilePosition, SourceDatabase};
|
||||||
use ide_db::{call_info::ActiveParameter, RootDatabase};
|
use ide_db::{call_info::ActiveParameter, RootDatabase};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::find_node_at_offset, ast, match_ast, AstNode, NodeOrToken, SyntaxKind::*, SyntaxNode,
|
algo::find_node_at_offset,
|
||||||
SyntaxToken, TextRange, TextSize,
|
ast::{self, NameOrNameRef, NameOwner},
|
||||||
|
match_ast, AstNode, NodeOrToken,
|
||||||
|
SyntaxKind::*,
|
||||||
|
SyntaxNode, SyntaxToken, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use text_edit::Indel;
|
use text_edit::Indel;
|
||||||
@ -35,7 +38,7 @@ pub(crate) struct CompletionContext<'a> {
|
|||||||
/// The token before the cursor, in the macro-expanded file.
|
/// The token before the cursor, in the macro-expanded file.
|
||||||
pub(super) token: SyntaxToken,
|
pub(super) token: SyntaxToken,
|
||||||
pub(super) krate: Option<hir::Crate>,
|
pub(super) krate: Option<hir::Crate>,
|
||||||
pub(super) expected_name: Option<String>,
|
pub(super) expected_name: Option<NameOrNameRef>,
|
||||||
pub(super) expected_type: Option<Type>,
|
pub(super) expected_type: Option<Type>,
|
||||||
pub(super) name_ref_syntax: Option<ast::NameRef>,
|
pub(super) name_ref_syntax: Option<ast::NameRef>,
|
||||||
pub(super) function_syntax: Option<ast::Fn>,
|
pub(super) function_syntax: Option<ast::Fn>,
|
||||||
@ -292,13 +295,13 @@ fn fill(
|
|||||||
file_with_fake_ident: SyntaxNode,
|
file_with_fake_ident: SyntaxNode,
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
) {
|
) {
|
||||||
let expected = {
|
let (expected_type, expected_name) = {
|
||||||
let mut node = match self.token.parent() {
|
let mut node = match self.token.parent() {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
let ret = match_ast! {
|
break match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::LetStmt(it) => {
|
ast::LetStmt(it) => {
|
||||||
cov_mark::hit!(expected_type_let_with_leading_char);
|
cov_mark::hit!(expected_type_let_with_leading_char);
|
||||||
@ -306,7 +309,7 @@ fn fill(
|
|||||||
let ty = it.pat()
|
let ty = it.pat()
|
||||||
.and_then(|pat| self.sema.type_of_pat(&pat));
|
.and_then(|pat| self.sema.type_of_pat(&pat));
|
||||||
let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() {
|
let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() {
|
||||||
Some(ident.syntax().text().to_string())
|
ident.name().map(NameOrNameRef::Name)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -319,7 +322,10 @@ fn fill(
|
|||||||
ActiveParameter::at_token(
|
ActiveParameter::at_token(
|
||||||
&self.sema,
|
&self.sema,
|
||||||
self.token.clone(),
|
self.token.clone(),
|
||||||
).map(|ap| (Some(ap.ty), Some(ap.name)))
|
).map(|ap| {
|
||||||
|
let name = ap.ident().map(NameOrNameRef::Name);
|
||||||
|
(Some(ap.ty), name)
|
||||||
|
})
|
||||||
.unwrap_or((None, None))
|
.unwrap_or((None, None))
|
||||||
},
|
},
|
||||||
ast::RecordExprFieldList(_it) => {
|
ast::RecordExprFieldList(_it) => {
|
||||||
@ -327,10 +333,10 @@ fn fill(
|
|||||||
self.token.prev_sibling_or_token()
|
self.token.prev_sibling_or_token()
|
||||||
.and_then(|se| se.into_node())
|
.and_then(|se| se.into_node())
|
||||||
.and_then(|node| ast::RecordExprField::cast(node))
|
.and_then(|node| ast::RecordExprField::cast(node))
|
||||||
.and_then(|rf| self.sema.resolve_record_field(&rf))
|
.and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf)))
|
||||||
.map(|f|(
|
.map(|(f, rf)|(
|
||||||
Some(f.0.signature_ty(self.db)),
|
Some(f.0.signature_ty(self.db)),
|
||||||
Some(f.0.name(self.db).to_string()),
|
rf.field_name().map(NameOrNameRef::NameRef),
|
||||||
))
|
))
|
||||||
.unwrap_or((None, None))
|
.unwrap_or((None, None))
|
||||||
},
|
},
|
||||||
@ -340,7 +346,7 @@ fn fill(
|
|||||||
.resolve_record_field(&it)
|
.resolve_record_field(&it)
|
||||||
.map(|f|(
|
.map(|f|(
|
||||||
Some(f.0.signature_ty(self.db)),
|
Some(f.0.signature_ty(self.db)),
|
||||||
Some(f.0.name(self.db).to_string()),
|
it.field_name().map(NameOrNameRef::NameRef),
|
||||||
))
|
))
|
||||||
.unwrap_or((None, None))
|
.unwrap_or((None, None))
|
||||||
},
|
},
|
||||||
@ -378,12 +384,10 @@ fn fill(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
break ret;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.expected_type = expected.0;
|
self.expected_type = expected_type;
|
||||||
self.expected_name = expected.1;
|
self.expected_name = expected_name;
|
||||||
self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
|
self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
|
||||||
|
|
||||||
// First, let's try to complete a reference to some declaration.
|
// First, let's try to complete a reference to some declaration.
|
||||||
@ -631,7 +635,9 @@ fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
|
|||||||
.map(|t| t.display_test(&db).to_string())
|
.map(|t| t.display_test(&db).to_string())
|
||||||
.unwrap_or("?".to_owned());
|
.unwrap_or("?".to_owned());
|
||||||
|
|
||||||
let name = completion_context.expected_name.unwrap_or("?".to_owned());
|
let name = completion_context
|
||||||
|
.expected_name
|
||||||
|
.map_or_else(|| "?".to_owned(), |name| name.to_string());
|
||||||
|
|
||||||
expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
|
expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ fn render_resolution(
|
|||||||
|
|
||||||
item.set_relevance(CompletionRelevance {
|
item.set_relevance(CompletionRelevance {
|
||||||
exact_type_match: compute_exact_type_match(self.ctx.completion, &ty),
|
exact_type_match: compute_exact_type_match(self.ctx.completion, &ty),
|
||||||
exact_name_match: compute_exact_name_match(self.ctx.completion, local_name.clone()),
|
exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name),
|
||||||
is_local: true,
|
is_local: true,
|
||||||
..CompletionRelevance::default()
|
..CompletionRelevance::default()
|
||||||
});
|
});
|
||||||
@ -319,8 +319,7 @@ fn compute_exact_type_match(ctx: &CompletionContext, completion_ty: &hir::Type)
|
|||||||
|
|
||||||
fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool {
|
fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool {
|
||||||
let completion_name = completion_name.into();
|
let completion_name = completion_name.into();
|
||||||
|
ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
|
||||||
Some(&completion_name) == ctx.expected_name.as_ref()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> {
|
fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use hir::{HasAttrs, HirDisplay, Semantics, Type};
|
use hir::{HasAttrs, HirDisplay, Semantics, Type};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, ArgListOwner},
|
ast::{self, ArgListOwner, NameOwner},
|
||||||
match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize,
|
match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ fn call_info_impl(
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ActiveParameter {
|
pub struct ActiveParameter {
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
pub name: String,
|
pub pat: Either<ast::SelfParam, ast::Pat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveParameter {
|
impl ActiveParameter {
|
||||||
@ -165,8 +165,14 @@ pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Se
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (pat, ty) = params.swap_remove(idx);
|
let (pat, ty) = params.swap_remove(idx);
|
||||||
let name = pat?.to_string();
|
pat.map(|pat| ActiveParameter { ty, pat })
|
||||||
Some(ActiveParameter { ty, name })
|
}
|
||||||
|
|
||||||
|
pub fn ident(&self) -> Option<ast::Name> {
|
||||||
|
self.pat.as_ref().right().and_then(|param| match param {
|
||||||
|
ast::Pat::IdentPat(ident) => ident.name(),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +380,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NameOrNameRef {
|
||||||
|
pub fn text(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
NameOrNameRef::Name(name) => name.text(),
|
||||||
|
NameOrNameRef::NameRef(name_ref) => name_ref.text(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ast::RecordPatField {
|
impl ast::RecordPatField {
|
||||||
pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
|
pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
|
||||||
let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
|
let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user