Skip to content

Commit 75fb3de

Browse files
committed
Handle generic args per arg index
Add more test cases for generic args
1 parent 0f2eba5 commit 75fb3de

File tree

4 files changed

+220
-45
lines changed

4 files changed

+220
-45
lines changed

crates/hir-def/src/generics.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct LifetimeParamData {
4747
pub struct ConstParamData {
4848
pub name: Name,
4949
pub ty: Interned<TypeRef>,
50+
pub has_default: bool,
5051
}
5152

5253
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -70,6 +71,13 @@ impl TypeOrConstParamData {
7071
}
7172
}
7273

74+
pub fn has_default(&self) -> bool {
75+
match self {
76+
TypeOrConstParamData::TypeParamData(x) => x.default.is_some(),
77+
TypeOrConstParamData::ConstParamData(x) => x.has_default,
78+
}
79+
}
80+
7381
pub fn type_param(&self) -> Option<&TypeParamData> {
7482
match self {
7583
TypeOrConstParamData::TypeParamData(x) => Some(x),
@@ -232,7 +240,11 @@ impl GenericParams {
232240
let ty = const_param
233241
.ty()
234242
.map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
235-
let param = ConstParamData { name, ty: Interned::new(ty) };
243+
let param = ConstParamData {
244+
name,
245+
ty: Interned::new(ty),
246+
has_default: const_param.default_val().is_some(),
247+
};
236248
self.type_or_consts.alloc(param.into());
237249
}
238250
}

crates/hir/src/lib.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,7 +1709,11 @@ impl Trait {
17091709
db.trait_data(self.id).is_unsafe
17101710
}
17111711

1712-
pub fn type_parameters(&self, db: &dyn HirDatabase) -> Vec<TypeOrConstParamData> {
1712+
pub fn type_or_const_param_count(
1713+
&self,
1714+
db: &dyn HirDatabase,
1715+
count_required_only: bool,
1716+
) -> usize {
17131717
db.generic_params(GenericDefId::from(self.id))
17141718
.type_or_consts
17151719
.iter()
@@ -1721,9 +1725,9 @@ impl Trait {
17211725
}
17221726
_ => true,
17231727
})
1724-
.map(|(_, ty)|ty.clone())
1725-
.collect()
1726-
}
1728+
.filter(|(_, ty)| !count_required_only || !ty.has_default())
1729+
.count()
1730+
}
17271731
}
17281732

17291733
impl HasVisibility for Trait {

crates/ide-completion/src/completions/type.rs

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Completion of names from the current scope in type position.
22
33
use hir::{HirDisplay, ScopeDef};
4-
use itertools::Itertools;
5-
use syntax::{ast, AstNode};
4+
use syntax::{ast, AstNode, SyntaxKind};
65

76
use crate::{
87
context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
@@ -141,34 +140,36 @@ pub(crate) fn complete_type_path(
141140
return;
142141
}
143142
TypeLocation::GenericArgList(Some(arg_list)) => {
144-
// the current token is in which generic arg
145-
let arg_pos = if let Some((pos, _)) =
146-
arg_list.generic_args().find_position(|arg| {
147-
arg.syntax()
148-
.descendants_with_tokens()
149-
.any(|t| t.as_token() == Some(&ctx.original_token))
150-
}) {
151-
pos
152-
} else {
153-
0
154-
};
143+
let in_assoc_type_arg = ctx
144+
.original_token
145+
.parent_ancestors()
146+
.any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
155147

156-
match arg_list.generic_args().next() {
157-
Some(ast::GenericArg::AssocTypeArg(_)) => {}
158-
_ => {
159-
if let Some(path_seg) =
160-
arg_list.syntax().parent().and_then(ast::PathSegment::cast)
148+
if !in_assoc_type_arg {
149+
if let Some(path_seg) =
150+
arg_list.syntax().parent().and_then(ast::PathSegment::cast)
151+
{
152+
if path_seg
153+
.syntax()
154+
.ancestors()
155+
.find_map(ast::TypeBound::cast)
156+
.is_some()
161157
{
162-
if path_seg
163-
.syntax()
164-
.ancestors()
165-
.find_map(ast::TypeBound::cast)
166-
.is_some()
158+
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
159+
trait_,
160+
))) = ctx.sema.resolve_path(&path_seg.parent_path())
167161
{
168-
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
169-
trait_,
170-
))) = ctx.sema.resolve_path(&path_seg.parent_path())
171-
{
162+
let arg_idx = arg_list
163+
.generic_args()
164+
.filter(|arg| {
165+
arg.syntax().text_range().end()
166+
< ctx.original_token.text_range().start()
167+
})
168+
.count();
169+
170+
let n_required_params =
171+
trait_.type_or_const_param_count(ctx.sema.db, true);
172+
if arg_idx >= n_required_params {
172173
trait_
173174
.items_with_supertraits(ctx.sema.db)
174175
.into_iter()
@@ -180,10 +181,12 @@ pub(crate) fn complete_type_path(
180181
acc.add_type_alias_with_eq(ctx, alias);
181182
}
182183
});
184+
}
183185

184-
if arg_pos >= trait_.type_parameters(ctx.sema.db).len() {
185-
return; // only AssocTypeArgs make sense
186-
}
186+
let n_params =
187+
trait_.type_or_const_param_count(ctx.sema.db, false);
188+
if arg_idx >= n_params {
189+
return; // only show assoc types
187190
}
188191
}
189192
}

crates/ide-completion/src/tests/type_pos.rs

Lines changed: 166 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,14 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
399399
ct CONST
400400
cp CONST_PARAM
401401
en Enum
402-
ma makro!(…) macro_rules! makro
402+
ma makro!(…) macro_rules! makro
403403
md module
404404
st Record
405405
st Tuple
406406
st Unit
407407
tt Trait
408408
tt Trait1
409409
tt Trait2
410-
ta Foo = (as Trait2) type Foo
411-
ta Super = (as Trait1) type Super
412410
tp T
413411
un Union
414412
bt u32
@@ -490,17 +488,147 @@ fn func(_: Enum::$0) {}
490488
}
491489

492490
#[test]
493-
fn completes_associated_type_only() {
491+
fn completes_type_parameter_or_associated_type() {
492+
check(
493+
r#"
494+
trait MyTrait<T, U> {
495+
type Item1;
496+
type Item2;
497+
};
498+
499+
fn f(t: impl MyTrait<u$0
500+
"#,
501+
expect![[r#"
502+
ct CONST
503+
en Enum
504+
ma makro!(…) macro_rules! makro
505+
md module
506+
st Record
507+
st Tuple
508+
st Unit
509+
tt MyTrait
510+
tt Trait
511+
un Union
512+
bt u32
513+
kw crate::
514+
kw self::
515+
kw super::
516+
"#]],
517+
);
518+
519+
check(
520+
r#"
521+
trait MyTrait<T, U> {
522+
type Item1;
523+
type Item2;
524+
};
525+
526+
fn f(t: impl MyTrait<u8, u$0
527+
"#,
528+
expect![[r#"
529+
ct CONST
530+
en Enum
531+
ma makro!(…) macro_rules! makro
532+
md module
533+
st Record
534+
st Tuple
535+
st Unit
536+
tt MyTrait
537+
tt Trait
538+
un Union
539+
bt u32
540+
kw crate::
541+
kw self::
542+
kw super::
543+
"#]],
544+
);
545+
546+
check(
547+
r#"
548+
trait MyTrait<T, U> {
549+
type Item1;
550+
type Item2;
551+
};
552+
553+
fn f(t: impl MyTrait<u8, u8, I$0
554+
"#,
555+
expect![[r#"
556+
ta Item1 = (as MyTrait) type Item1
557+
ta Item2 = (as MyTrait) type Item2
558+
"#]],
559+
);
560+
}
561+
562+
#[test]
563+
fn completes_type_parameter_or_associated_type_with_default_value() {
564+
check(
565+
r#"
566+
trait MyTrait<T = u8, U> {
567+
type Item1;
568+
type Item2;
569+
};
570+
571+
fn f(t: impl MyTrait<u$0
572+
"#,
573+
expect![[r#"
574+
ct CONST
575+
en Enum
576+
ma makro!(…) macro_rules! makro
577+
md module
578+
st Record
579+
st Tuple
580+
st Unit
581+
tt MyTrait
582+
tt Trait
583+
un Union
584+
bt u32
585+
kw crate::
586+
kw self::
587+
kw super::
588+
"#]],
589+
);
590+
591+
check(
592+
r#"
593+
trait MyTrait<T = u8, U> {
594+
type Item1;
595+
type Item2;
596+
};
597+
598+
fn f(t: impl MyTrait<u8, u$0
599+
"#,
600+
expect![[r#"
601+
ct CONST
602+
en Enum
603+
ma makro!(…) macro_rules! makro
604+
md module
605+
st Record
606+
st Tuple
607+
st Unit
608+
tt MyTrait
609+
tt Trait
610+
ta Item1 = (as MyTrait) type Item1
611+
ta Item2 = (as MyTrait) type Item2
612+
un Union
613+
bt u32
614+
kw crate::
615+
kw self::
616+
kw super::
617+
"#]],
618+
);
619+
494620
check(
495621
r#"
496-
trait MyTrait<T> {
497-
type Item;
622+
trait MyTrait<T = u8, U> {
623+
type Item1;
624+
type Item2;
498625
};
499626
500-
fn f(t: impl MyTrait<u8,I$0
627+
fn f(t: impl MyTrait<u8, u8, I$0
501628
"#,
502629
expect![[r#"
503-
ta Item = (as MyTrait) type Item
630+
ta Item1 = (as MyTrait) type Item1
631+
ta Item2 = (as MyTrait) type Item2
504632
"#]],
505633
);
506634
}
@@ -510,10 +638,38 @@ fn completes_types_after_associated_type() {
510638
check(
511639
r#"
512640
trait MyTrait {
513-
type Item;
641+
type Item1;
642+
type Item2;
643+
};
644+
645+
fn f(t: impl MyTrait<Item1 = $0
646+
"#,
647+
expect![[r#"
648+
ct CONST
649+
en Enum
650+
ma makro!(…) macro_rules! makro
651+
md module
652+
st Record
653+
st Tuple
654+
st Unit
655+
tt MyTrait
656+
tt Trait
657+
un Union
658+
bt u32
659+
kw crate::
660+
kw self::
661+
kw super::
662+
"#]],
663+
);
664+
665+
check(
666+
r#"
667+
trait MyTrait {
668+
type Item1;
669+
type Item2;
514670
};
515671
516-
fn f(t: impl MyTrait<Item = $0
672+
fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
517673
"#,
518674
expect![[r#"
519675
ct CONST

0 commit comments

Comments
 (0)