Merge pull request #18436 from Veykril/lw-yvkqwpnwsouo

Do not render meta info when hovering usages
This commit is contained in:
Lukas Wirth 2024-10-30 09:21:35 +00:00 committed by GitHub
commit 436ace3ecb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 479 additions and 192 deletions

View file

@ -34,7 +34,10 @@ pub mod term_search;
mod display; mod display;
use std::{mem::discriminant, ops::ControlFlow}; use std::{
mem::discriminant,
ops::{ControlFlow, Not},
};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, CrateOrigin}; use base_db::{CrateDisplayName, CrateId, CrateOrigin};
@ -2697,6 +2700,18 @@ impl Trait {
hir_ty::dyn_compatibility::dyn_compatibility(db, self.id) hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
} }
pub fn dyn_compatibility_all_violations(
&self,
db: &dyn HirDatabase,
) -> Option<Vec<DynCompatibilityViolation>> {
let mut violations = vec![];
hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
violations.push(violation);
ControlFlow::Continue(())
});
violations.is_empty().not().then_some(violations)
}
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
db.trait_data(self.id) db.trait_data(self.id)
.macro_calls .macro_calls

View file

@ -158,7 +158,7 @@ fn hover_offset(
if let Some(doc_comment) = token_as_doc_comment(&original_token) { if let Some(doc_comment) = token_as_doc_comment(&original_token) {
cov_mark::hit!(no_highlight_on_comment_hover); cov_mark::hit!(no_highlight_on_comment_hover);
return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| { return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
let res = hover_for_definition(sema, file_id, def, &node, None, config, edition); let res = hover_for_definition(sema, file_id, def, &node, None, false, config, edition);
Some(RangeInfo::new(range, res)) Some(RangeInfo::new(range, res))
}); });
} }
@ -172,6 +172,7 @@ fn hover_offset(
Definition::from(resolution?), Definition::from(resolution?),
&original_token.parent()?, &original_token.parent()?,
None, None,
false,
config, config,
edition, edition,
); );
@ -218,6 +219,7 @@ fn hover_offset(
break 'a vec![( break 'a vec![(
Definition::Macro(macro_), Definition::Macro(macro_),
sema.resolve_macro_call_arm(&macro_call), sema.resolve_macro_call_arm(&macro_call),
false,
node, node,
)]; )];
} }
@ -234,19 +236,34 @@ fn hover_offset(
decl, decl,
.. ..
}) => { }) => {
vec![(Definition::ExternCrateDecl(decl), None, node)] vec![(Definition::ExternCrateDecl(decl), None, false, node)]
} }
class => { class => {
multizip((class.definitions(), iter::repeat(None), iter::repeat(node))) let is_def = matches!(class, IdentClass::NameClass(_));
.collect::<Vec<_>>() multizip((
class.definitions(),
iter::repeat(None),
iter::repeat(is_def),
iter::repeat(node),
))
.collect::<Vec<_>>()
} }
} }
} }
.into_iter() .into_iter()
.unique_by(|&(def, _, _)| def) .unique_by(|&(def, _, _, _)| def)
.map(|(def, macro_arm, node)| { .map(|(def, macro_arm, hovered_definition, node)| {
hover_for_definition(sema, file_id, def, &node, macro_arm, config, edition) hover_for_definition(
sema,
file_id,
def,
&node,
macro_arm,
hovered_definition,
config,
edition,
)
}) })
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) )
@ -366,6 +383,7 @@ pub(crate) fn hover_for_definition(
def: Definition, def: Definition,
scope_node: &SyntaxNode, scope_node: &SyntaxNode,
macro_arm: Option<u32>, macro_arm: Option<u32>,
hovered_definition: bool,
config: &HoverConfig, config: &HoverConfig,
edition: Edition, edition: Edition,
) -> HoverResult { ) -> HoverResult {
@ -397,6 +415,7 @@ pub(crate) fn hover_for_definition(
famous_defs.as_ref(), famous_defs.as_ref(),
&notable_traits, &notable_traits,
macro_arm, macro_arm,
hovered_definition,
config, config,
edition, edition,
); );

View file

@ -273,7 +273,7 @@ pub(super) fn keyword(
let markup = process_markup( let markup = process_markup(
sema.db, sema.db,
Definition::Module(doc_owner), Definition::Module(doc_owner),
&markup(Some(docs.into()), description, None), &markup(Some(docs.into()), description, None, None),
config, config,
); );
Some(HoverResult { markup, actions }) Some(HoverResult { markup, actions })
@ -419,6 +419,7 @@ pub(super) fn definition(
famous_defs: Option<&FamousDefs<'_, '_>>, famous_defs: Option<&FamousDefs<'_, '_>>,
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
macro_arm: Option<u32>, macro_arm: Option<u32>,
hovered_definition: bool,
config: &HoverConfig, config: &HoverConfig,
edition: Edition, edition: Edition,
) -> Markup { ) -> Markup {
@ -456,7 +457,7 @@ pub(super) fn definition(
_ => def.label(db, edition), _ => def.label(db, edition),
}; };
let docs = def.docs(db, famous_defs, edition); let docs = def.docs(db, famous_defs, edition);
let value = (|| match def { let value = || match def {
Definition::Variant(it) => { Definition::Variant(it) => {
if !it.parent_enum(db).is_data_carrying(db) { if !it.parent_enum(db).is_data_carrying(db) {
match it.eval(db) { match it.eval(db) {
@ -494,9 +495,9 @@ pub(super) fn definition(
Some(body.to_string()) Some(body.to_string())
} }
_ => None, _ => None,
})(); };
let layout_info = match def { let layout_info = || match def {
Definition::Field(it) => render_memory_layout( Definition::Field(it) => render_memory_layout(
config.memory_layout, config.memory_layout,
|| it.layout(db), || it.layout(db),
@ -529,34 +530,38 @@ pub(super) fn definition(
_ => None, _ => None,
}; };
let dyn_compatibility_info = if let Definition::Trait(it) = def { let dyn_compatibility_info = || match def {
let mut dyn_compatibility_info = String::new(); Definition::Trait(it) => {
render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db)); let mut dyn_compatibility_info = String::new();
Some(dyn_compatibility_info) render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db));
} else { Some(dyn_compatibility_info)
None }
_ => None,
}; };
let mut extra = String::new();
if hovered_definition {
if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) {
extra.push_str("\n___\n");
extra.push_str(&notable_traits);
}
if let Some(layout_info) = layout_info() {
extra.push_str("\n___\n");
extra.push_str(&layout_info);
}
if let Some(dyn_compatibility_info) = dyn_compatibility_info() {
extra.push_str("\n___\n");
extra.push_str(&dyn_compatibility_info);
}
}
let mut desc = String::new(); let mut desc = String::new();
if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) {
desc.push_str(&notable_traits);
desc.push('\n');
}
if let Some(layout_info) = layout_info {
desc.push_str(&layout_info);
desc.push('\n');
}
if let Some(dyn_compatibility_info) = dyn_compatibility_info {
desc.push_str(&dyn_compatibility_info);
desc.push('\n');
}
desc.push_str(&label); desc.push_str(&label);
if let Some(value) = value { if let Some(value) = value() {
desc.push_str(" = "); desc.push_str(" = ");
desc.push_str(&value); desc.push_str(&value);
} }
markup(docs.map(Into::into), desc, mod_path) markup(docs.map(Into::into), desc, extra.is_empty().not().then_some(extra), mod_path)
} }
pub(super) fn literal( pub(super) fn literal(
@ -626,7 +631,7 @@ pub(super) fn literal(
Some(s.into()) Some(s.into())
} }
fn render_notable_trait_comment( fn render_notable_trait(
db: &RootDatabase, db: &RootDatabase,
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
edition: Edition, edition: Edition,
@ -635,7 +640,7 @@ fn render_notable_trait_comment(
let mut needs_impl_header = true; let mut needs_impl_header = true;
for (trait_, assoc_types) in notable_traits { for (trait_, assoc_types) in notable_traits {
desc.push_str(if mem::take(&mut needs_impl_header) { desc.push_str(if mem::take(&mut needs_impl_header) {
"// Implements notable traits: " "Implements notable traits: "
} else { } else {
", " ", "
}); });
@ -728,13 +733,12 @@ fn type_info(
) )
.into() .into()
} else { } else {
let mut desc = let mut desc = format!("```rust\n{}\n```", original.display(db, edition));
match render_notable_trait_comment(db, &notable_traits(db, &original), edition) { if let Some(extra) = render_notable_trait(db, &notable_traits(db, &original), edition) {
Some(desc) => desc + "\n", desc.push_str("\n___\n");
None => String::new(), desc.push_str(&extra);
}; };
format_to!(desc, "{}", original.display(db, edition)); desc.into()
Markup::fenced_block(&desc)
}; };
if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) { if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) {
res.actions.push(actions); res.actions.push(actions);
@ -786,20 +790,16 @@ fn closure_ty(
}; };
let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition)); let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition));
if let Some(layout) =
render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
{
format_to!(markup, " {layout}");
}
if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
push_new_def(hir::Trait::from(trait_).into()) push_new_def(hir::Trait::from(trait_).into())
} }
format_to!( format_to!(markup, "\n{}\n```", c.display_with_impl(sema.db, edition),);
markup, if let Some(layout) =
"\n{}\n```{adjusted}\n\n## Captures\n{}", render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
c.display_with_impl(sema.db, edition), {
captures_rendered, format_to!(markup, "\n___\n{layout}");
); }
format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,);
let mut res = HoverResult::default(); let mut res = HoverResult::default();
if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
@ -824,7 +824,12 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) ->
.map(|module| path(db, module, definition_owner_name(db, def, edition), edition)) .map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
} }
fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup { fn markup(
docs: Option<String>,
rust: String,
extra: Option<String>,
mod_path: Option<String>,
) -> Markup {
let mut buf = String::new(); let mut buf = String::new();
if let Some(mod_path) = mod_path { if let Some(mod_path) = mod_path {
@ -832,7 +837,11 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Marku
format_to!(buf, "```rust\n{}\n```\n\n", mod_path); format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
} }
} }
format_to!(buf, "```rust\n{}\n```", desc); format_to!(buf, "```rust\n{}\n```", rust);
if let Some(extra) = extra {
buf.push_str(&extra);
}
if let Some(doc) = docs { if let Some(doc) = docs {
format_to!(buf, "\n___\n\n{}", doc); format_to!(buf, "\n___\n\n{}", doc);
@ -862,7 +871,7 @@ fn render_memory_layout(
let config = config?; let config = config?;
let layout = layout().ok()?; let layout = layout().ok()?;
let mut label = String::from("// "); let mut label = String::new();
if let Some(render) = config.size { if let Some(render) = config.size {
let size = match tag(&layout) { let size = match tag(&layout) {
@ -994,55 +1003,53 @@ fn render_dyn_compatibility(
safety: Option<DynCompatibilityViolation>, safety: Option<DynCompatibilityViolation>,
) { ) {
let Some(osv) = safety else { let Some(osv) = safety else {
buf.push_str("// Dyn Compatible: Yes"); buf.push_str("Is Dyn compatible");
return; return;
}; };
buf.push_str("// Dyn Compatible: No\n// - Reason: "); buf.push_str("Is not Dyn compatible due to ");
match osv { match osv {
DynCompatibilityViolation::SizedSelf => { DynCompatibilityViolation::SizedSelf => {
buf.push_str("has a `Self: Sized` bound"); buf.push_str("having a `Self: Sized` bound");
} }
DynCompatibilityViolation::SelfReferential => { DynCompatibilityViolation::SelfReferential => {
buf.push_str("has a bound that references `Self`"); buf.push_str("having a bound that references `Self`");
} }
DynCompatibilityViolation::Method(func, mvc) => { DynCompatibilityViolation::Method(func, mvc) => {
let name = hir::Function::from(func).name(db); let name = hir::Function::from(func).name(db);
format_to!( format_to!(buf, "having a method `{}` that is not dispatchable due to ", name.as_str());
buf,
"has a method `{}` that is non dispatchable because of:\n// - ",
name.as_str()
);
let desc = match mvc { let desc = match mvc {
MethodViolationCode::StaticMethod => "missing a receiver", MethodViolationCode::StaticMethod => "missing a receiver",
MethodViolationCode::ReferencesSelfInput => "a parameter references `Self`", MethodViolationCode::ReferencesSelfInput => "having a parameter referencing `Self`",
MethodViolationCode::ReferencesSelfOutput => "the return type references `Self`", MethodViolationCode::ReferencesSelfOutput => "the return type referencing `Self`",
MethodViolationCode::ReferencesImplTraitInTrait => { MethodViolationCode::ReferencesImplTraitInTrait => {
"the return type contains `impl Trait`" "the return type containing `impl Trait`"
} }
MethodViolationCode::AsyncFn => "being async", MethodViolationCode::AsyncFn => "being async",
MethodViolationCode::WhereClauseReferencesSelf => { MethodViolationCode::WhereClauseReferencesSelf => {
"a where clause references `Self`" "a where clause referencing `Self`"
}
MethodViolationCode::Generic => "having a const or type generic parameter",
MethodViolationCode::UndispatchableReceiver => {
"having a non-dispatchable receiver type"
} }
MethodViolationCode::Generic => "a non-lifetime generic parameter",
MethodViolationCode::UndispatchableReceiver => "a non-dispatchable receiver type",
}; };
buf.push_str(desc); buf.push_str(desc);
} }
DynCompatibilityViolation::AssocConst(const_) => { DynCompatibilityViolation::AssocConst(const_) => {
let name = hir::Const::from(const_).name(db); let name = hir::Const::from(const_).name(db);
if let Some(name) = name { if let Some(name) = name {
format_to!(buf, "has an associated constant `{}`", name.as_str()); format_to!(buf, "having an associated constant `{}`", name.as_str());
} else { } else {
buf.push_str("has an associated constant"); buf.push_str("having an associated constant");
} }
} }
DynCompatibilityViolation::GAT(alias) => { DynCompatibilityViolation::GAT(alias) => {
let name = hir::TypeAlias::from(alias).name(db); let name = hir::TypeAlias::from(alias).name(db);
format_to!(buf, "has a generic associated type `{}`", name.as_str()); format_to!(buf, "having a generic associated type `{}`", name.as_str());
} }
DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => { DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => {
let name = hir::Trait::from(super_trait).name(db); let name = hir::Trait::from(super_trait).name(db);
format_to!(buf, "has a dyn incompatible supertrait `{}`", name.as_str()); format_to!(buf, "having a dyn incompatible supertrait `{}`", name.as_str());
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -212,6 +212,7 @@ impl StaticIndex<'_> {
def, def,
&node, &node,
None, None,
false,
&hover_config, &hover_config,
edition, edition,
)), )),