Properly use location links for type hints of impl Future and its assoc type

This commit is contained in:
Lukas Wirth 2023-02-07 22:42:03 +01:00
parent 0b32b65ca6
commit 2b4a5374ee
4 changed files with 106 additions and 12 deletions

View File

@ -12,7 +12,7 @@
find_path, find_path,
generics::{TypeOrConstParamData, TypeParamProvenance}, generics::{TypeOrConstParamData, TypeParamProvenance},
item_scope::ItemInNs, item_scope::ItemInNs,
lang_item::LangItem, lang_item::{LangItem, LangItemTarget},
path::{Path, PathKind}, path::{Path, PathKind},
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef}, type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility, visibility::Visibility,
@ -731,8 +731,30 @@ fn should_show(
)?; )?;
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
} }
ImplTraitId::AsyncBlockTypeImplTrait(..) => { ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
write!(f, "impl Future<Output = ")?; let future_trait = db
.lang_item(body.module(db.upcast()).krate(), LangItem::Future)
.and_then(LangItemTarget::as_trait);
let output = future_trait.and_then(|t| {
db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output))
});
write!(f, "impl ")?;
if let Some(t) = future_trait {
f.start_location_link(t.into());
}
write!(f, "Future")?;
if let Some(_) = future_trait {
f.end_location_link();
}
write!(f, "<")?;
if let Some(t) = output {
f.start_location_link(t.into());
}
write!(f, "Output")?;
if let Some(_) = output {
f.end_location_link();
}
write!(f, " = ")?;
parameters.at(Interner, 0).hir_fmt(f)?; parameters.at(Interner, 0).hir_fmt(f)?;
write!(f, ">")?; write!(f, ">")?;
} }

View File

@ -294,10 +294,12 @@ fn rec(
) -> Result<(), HirDisplayError> { ) -> Result<(), HirDisplayError> {
let iter_item_type = hint_iterator(sema, famous_defs, &ty); let iter_item_type = hint_iterator(sema, famous_defs, &ty);
match iter_item_type { match iter_item_type {
Some((iter_trait, ty)) => { Some((iter_trait, item, ty)) => {
const LABEL_START: &str = "impl "; const LABEL_START: &str = "impl ";
const LABEL_ITERATOR: &str = "Iterator"; const LABEL_ITERATOR: &str = "Iterator";
const LABEL_MIDDLE: &str = "<Item = "; const LABEL_MIDDLE: &str = "<";
const LABEL_ITEM: &str = "Item";
const LABEL_MIDDLE2: &str = " = ";
const LABEL_END: &str = ">"; const LABEL_END: &str = ">";
max_length = max_length.map(|len| { max_length = max_length.map(|len| {
@ -305,6 +307,7 @@ fn rec(
LABEL_START.len() LABEL_START.len()
+ LABEL_ITERATOR.len() + LABEL_ITERATOR.len()
+ LABEL_MIDDLE.len() + LABEL_MIDDLE.len()
+ LABEL_MIDDLE2.len()
+ LABEL_END.len(), + LABEL_END.len(),
) )
}); });
@ -314,6 +317,10 @@ fn rec(
label_builder.write_str(LABEL_ITERATOR)?; label_builder.write_str(LABEL_ITERATOR)?;
label_builder.end_location_link(); label_builder.end_location_link();
label_builder.write_str(LABEL_MIDDLE)?; label_builder.write_str(LABEL_MIDDLE)?;
label_builder.start_location_link(ModuleDef::from(item).into());
label_builder.write_str(LABEL_ITEM)?;
label_builder.end_location_link();
label_builder.write_str(LABEL_MIDDLE2)?;
rec(sema, famous_defs, max_length, ty, label_builder)?; rec(sema, famous_defs, max_length, ty, label_builder)?;
label_builder.write_str(LABEL_END)?; label_builder.write_str(LABEL_END)?;
Ok(()) Ok(())
@ -437,7 +444,7 @@ fn hint_iterator(
sema: &Semantics<'_, RootDatabase>, sema: &Semantics<'_, RootDatabase>,
famous_defs: &FamousDefs<'_, '_>, famous_defs: &FamousDefs<'_, '_>,
ty: &hir::Type, ty: &hir::Type,
) -> Option<(hir::Trait, hir::Type)> { ) -> Option<(hir::Trait, hir::TypeAlias, hir::Type)> {
let db = sema.db; let db = sema.db;
let strukt = ty.strip_references().as_adt()?; let strukt = ty.strip_references().as_adt()?;
let krate = strukt.module(db).krate(); let krate = strukt.module(db).krate();
@ -460,7 +467,7 @@ fn hint_iterator(
_ => None, _ => None,
})?; })?;
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) { if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
return Some((iter_trait, ty)); return Some((iter_trait, assoc_type_item, ty));
} }
} }

View File

@ -330,7 +330,20 @@ fn main(a: SliceIter<'_, Container>) {
), ),
tooltip: "", tooltip: "",
}, },
"<Item = impl ", "<",
InlayHintLabelPart {
text: "Item",
linked_location: Some(
FileRange {
file_id: FileId(
1,
),
range: 2643..2647,
},
),
tooltip: "",
},
" = impl ",
InlayHintLabelPart { InlayHintLabelPart {
text: "Iterator", text: "Iterator",
linked_location: Some( linked_location: Some(
@ -343,7 +356,20 @@ fn main(a: SliceIter<'_, Container>) {
), ),
tooltip: "", tooltip: "",
}, },
"<Item = &&str>>", "<",
InlayHintLabelPart {
text: "Item",
linked_location: Some(
FileRange {
file_id: FileId(
1,
),
range: 2643..2647,
},
),
tooltip: "",
},
" = &&str>>",
], ],
}, },
InlayHint { InlayHint {

View File

@ -440,7 +440,20 @@ fn main() {
), ),
tooltip: "", tooltip: "",
}, },
"<Item = ()>", "<",
InlayHintLabelPart {
text: "Item",
linked_location: Some(
FileRange {
file_id: FileId(
1,
),
range: 2643..2647,
},
),
tooltip: "",
},
" = ()>",
], ],
}, },
InlayHint { InlayHint {
@ -460,7 +473,20 @@ fn main() {
), ),
tooltip: "", tooltip: "",
}, },
"<Item = ()>", "<",
InlayHintLabelPart {
text: "Item",
linked_location: Some(
FileRange {
file_id: FileId(
1,
),
range: 2643..2647,
},
),
tooltip: "",
},
" = ()>",
], ],
}, },
InlayHint { InlayHint {
@ -480,7 +506,20 @@ fn main() {
), ),
tooltip: "", tooltip: "",
}, },
"<Item = ()>", "<",
InlayHintLabelPart {
text: "Item",
linked_location: Some(
FileRange {
file_id: FileId(
1,
),
range: 2643..2647,
},
),
tooltip: "",
},
" = ()>",
], ],
}, },
InlayHint { InlayHint {