working for path segments

This commit is contained in:
Max Heller 2023-07-30 15:36:42 -04:00
parent c4cff80269
commit b9ee4a5167
4 changed files with 76 additions and 38 deletions

View File

@ -24,12 +24,23 @@ pub(crate) fn complete_type_path(
// no values in type places // no values in type places
ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false, ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
// unless its a constant in a generic arg list position // unless its a constant in a generic arg list position
ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => { ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => match location
matches!(location, TypeLocation::GenericArgList(_)) {
TypeLocation::GenericArgList(location) => match location {
Some((_, Some(generic_param))) => {
matches!(generic_param, ast::GenericParam::ConstParam(_))
} }
ScopeDef::ImplSelfType(_) => { _ => true,
!matches!(location, TypeLocation::ImplTarget | TypeLocation::ImplTrait) },
_ => false,
},
ScopeDef::ImplSelfType(_) => match location {
TypeLocation::ImplTarget | TypeLocation::ImplTrait => false,
TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => {
matches!(generic_param, ast::GenericParam::TypeParam(_))
} }
_ => true,
},
// Don't suggest attribute macros and derives. // Don't suggest attribute macros and derives.
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db), ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
// Type things are fine // Type things are fine
@ -38,7 +49,12 @@ pub(crate) fn complete_type_path(
) )
| ScopeDef::AdtSelfType(_) | ScopeDef::AdtSelfType(_)
| ScopeDef::Unknown | ScopeDef::Unknown
| ScopeDef::GenericParam(TypeParam(_)) => true, | ScopeDef::GenericParam(TypeParam(_)) => match location {
TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => {
matches!(generic_param, ast::GenericParam::TypeParam(_))
}
_ => true,
},
} }
}; };
@ -157,7 +173,7 @@ pub(crate) fn complete_type_path(
}); });
return; return;
} }
TypeLocation::GenericArgList(Some(arg_list)) => { TypeLocation::GenericArgList(Some((arg_list, generic_param))) => {
let in_assoc_type_arg = ctx let in_assoc_type_arg = ctx
.original_token .original_token
.parent_ancestors() .parent_ancestors()

View File

@ -155,7 +155,7 @@ pub(crate) struct ExprCtx {
pub(crate) enum TypeLocation { pub(crate) enum TypeLocation {
TupleField, TupleField,
TypeAscription(TypeAscriptionTarget), TypeAscription(TypeAscriptionTarget),
GenericArgList(Option<ast::GenericArgList>), GenericArgList(Option<(ast::GenericArgList, Option<ast::GenericParam>)>),
TypeBound, TypeBound,
ImplTarget, ImplTarget,
ImplTrait, ImplTrait,

View File

@ -1,11 +1,11 @@
//! Module responsible for analyzing the code surrounding the cursor for completion. //! Module responsible for analyzing the code surrounding the cursor for completion.
use std::iter; use std::iter;
use hir::{Semantics, Type, TypeInfo, Variant}; use hir::{HasSource, Semantics, Type, TypeInfo, Variant};
use ide_db::{active_parameter::ActiveParameter, RootDatabase}; use ide_db::{active_parameter::ActiveParameter, RootDatabase};
use syntax::{ use syntax::{
algo::{find_node_at_offset, non_trivia_sibling}, algo::{find_node_at_offset, non_trivia_sibling},
ast::{self, AttrKind, HasArgList, HasLoopBody, HasName, NameOrNameRef}, ast::{self, AttrKind, HasArgList, HasGenericParams, HasLoopBody, HasName, NameOrNameRef},
match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
SyntaxToken, TextRange, TextSize, T, SyntaxToken, TextRange, TextSize, T,
}; };
@ -774,9 +774,40 @@ fn classify_name_ref(
ast::TypeBound(_) => TypeLocation::TypeBound, ast::TypeBound(_) => TypeLocation::TypeBound,
// is this case needed? // is this case needed?
ast::TypeBoundList(_) => TypeLocation::TypeBound, ast::TypeBoundList(_) => TypeLocation::TypeBound,
ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))), ast::GenericArg(it) => {
let location = find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))
.map(|args| {
// Determine the index of the parameter in the `GenericArgList`
// (subtract 1 because `siblings` includes the node itself)
let param_idx = it.syntax().siblings(Direction::Prev).count() - 1;
let param = args
.syntax()
.parent()
.and_then(|p| ast::PathSegment::cast(p))
.and_then(|segment| sema.resolve_path(&segment.parent_path().top_path()))
.and_then(|resolved| {
match resolved {
hir::PathResolution::Def(def) => match def {
hir::ModuleDef::Function(func) => {
let src = func.source(sema.db)?;
let params = src.value.generic_param_list()?;
params.generic_params().nth(param_idx)
}
_ => None,
},
_ => None,
}
});
(args, param)
});
TypeLocation::GenericArgList(location)
},
// is this case needed? // is this case needed?
ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))), ast::GenericArgList(it) => {
let location = find_opt_node_in_file_compensated(sema, original_file, Some(it))
.map(|node| (node, None));
TypeLocation::GenericArgList(location)
},
ast::TupleField(_) => TypeLocation::TupleField, ast::TupleField(_) => TypeLocation::TupleField,
_ => return None, _ => return None,
} }
@ -883,25 +914,8 @@ fn classify_name_ref(
} }
}; };
let make_path_kind_type = |ty: ast::Type| { let make_path_kind_type = |ty: ast::Type| {
let location = type_location(ty.syntax()).unwrap_or(TypeLocation::Other); let location = type_location(ty.syntax());
match &location { PathKind::Type { location: location.unwrap_or(TypeLocation::Other) }
TypeLocation::TupleField => (),
TypeLocation::TypeAscription(_) => (),
TypeLocation::GenericArgList(args) => {
dbg!(&args);
if let Some(segment) =
args.as_ref().and_then(|args| ast::PathSegment::cast(args.syntax().parent()?))
{
let path = dbg!(segment.parent_path().top_path());
dbg!(sema.resolve_path(&path));
}
}
TypeLocation::TypeBound => (),
TypeLocation::ImplTarget => (),
TypeLocation::ImplTrait => (),
TypeLocation::Other => (),
}
PathKind::Type { location }
}; };
let mut kind_macro_call = |it: ast::MacroCall| { let mut kind_macro_call = |it: ast::MacroCall| {

View File

@ -726,15 +726,21 @@ fn completes_const_and_type_generics_separately() {
r#" r#"
struct Foo; struct Foo;
const X: usize = 0; const X: usize = 0;
mod foo { fn foo<T, const N: usize>() {}
fn foo<T>() {}
}
fn main() { fn main() {
self::foo::foo::<F$0>(); foo::<F$0, _>();
} }
"#, "#,
expect![[r#" expect![[r#"
en Enum
ma makro!() macro_rules! makro
md module
st Foo st Foo
st Record
st Tuple
st Unit
tt Trait
un Union
bt u32 bt u32
kw crate:: kw crate::
kw self:: kw self::
@ -744,13 +750,15 @@ fn main() {
r#" r#"
struct Foo; struct Foo;
const X: usize = 0; const X: usize = 0;
fn foo<const X: usize>() {} fn foo<T, const N: usize>() {}
fn main() { fn main() {
foo::<F$0>(); foo::<_, $0>();
} }
"#, "#,
expect![[r#" expect![[r#"
ct CONST
ct X ct X
ma makro!() macro_rules! makro
kw crate:: kw crate::
kw self:: kw self::
"#]], "#]],