fix: Don't render fieldless discriminant inlay hints for datacarrying enums

This commit is contained in:
Lukas Wirth 2023-02-01 11:38:39 +01:00
parent 9814d79841
commit 14f19c73e9
2 changed files with 48 additions and 27 deletions

View File

@ -422,11 +422,9 @@ fn hints(
// static type elisions // static type elisions
ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)), ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)),
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)), ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it),
_ => None, _ => None,
}, },
ast::Variant(v) => {
discriminant::hints(hints, famous_defs, config, file_id, &v)
},
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions // FIXME: fn-ptr type, dyn fn type, and trait object type elisions
ast::Type(_) => None, ast::Type(_) => None,
_ => None, _ => None,

View File

@ -4,29 +4,40 @@
//! Bar/* = 0*/, //! Bar/* = 0*/,
//! } //! }
//! ``` //! ```
use ide_db::{base_db::FileId, famous_defs::FamousDefs}; use hir::Semantics;
use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
use syntax::ast::{self, AstNode, HasName}; use syntax::ast::{self, AstNode, HasName};
use crate::{ use crate::{
DiscriminantHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, DiscriminantHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip,
}; };
pub(super) fn hints( pub(super) fn enum_hints(
acc: &mut Vec<InlayHint>, acc: &mut Vec<InlayHint>,
FamousDefs(sema, _): &FamousDefs<'_, '_>, FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig, config: &InlayHintsConfig,
_: FileId, _: FileId,
enum_: ast::Enum,
) -> Option<()> {
let disabled = match config.discriminant_hints {
DiscriminantHints::Always => false,
DiscriminantHints::Fieldless => sema.to_def(&enum_)?.is_data_carrying(sema.db),
DiscriminantHints::Never => true,
};
if disabled {
return None;
}
for variant in enum_.variant_list()?.variants() {
variant_hints(acc, sema, &variant);
}
None
}
fn variant_hints(
acc: &mut Vec<InlayHint>,
sema: &Semantics<'_, RootDatabase>,
variant: &ast::Variant, variant: &ast::Variant,
) -> Option<()> { ) -> Option<()> {
let field_list = match config.discriminant_hints {
DiscriminantHints::Always => variant.field_list(),
DiscriminantHints::Fieldless => match variant.field_list() {
Some(_) => return None,
None => None,
},
DiscriminantHints::Never => return None,
};
if variant.eq_token().is_some() { if variant.eq_token().is_some() {
return None; return None;
} }
@ -39,7 +50,7 @@ pub(super) fn hints(
let d = v.eval(sema.db); let d = v.eval(sema.db);
acc.push(InlayHint { acc.push(InlayHint {
range: match field_list { range: match variant.field_list() {
Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()), Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()),
None => name.syntax().text_range(), None => name.syntax().text_range(),
}, },
@ -91,15 +102,30 @@ fn fieldless() {
check_discriminants( check_discriminants(
r#" r#"
enum Enum { enum Enum {
Variant, Variant,
//^^^^^^^0 //^^^^^^^0
Variant1, Variant1,
//^^^^^^^^1 //^^^^^^^^1
Variant2, Variant2,
//^^^^^^^^2 //^^^^^^^^2
Variant5 = 5, Variant5 = 5,
Variant6, Variant6,
//^^^^^^^^6 //^^^^^^^^6
}
"#,
);
check_discriminants_fieldless(
r#"
enum Enum {
Variant,
//^^^^^^^0
Variant1,
//^^^^^^^^1
Variant2,
//^^^^^^^^2
Variant5 = 5,
Variant6,
//^^^^^^^^6
} }
"#, "#,
); );
@ -133,13 +159,10 @@ fn datacarrying_mixed_fieldless_set() {
enum Enum { enum Enum {
Variant(), Variant(),
Variant1, Variant1,
//^^^^^^^^1
Variant2 {}, Variant2 {},
Variant3, Variant3,
//^^^^^^^^3
Variant5 = 5, Variant5 = 5,
Variant6, Variant6,
//^^^^^^^^6
} }
"#, "#,
); );