mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Auto merge of #13189 - unexge:unconfigured-diagnostics-for-fields, r=Veykril
Emit unconfigured code diagnostics for enum variants and struct/union fields Fixes https://github.com/rust-lang/rust-analyzer/issues/12664
This commit is contained in:
commit
b01cdd89d5
@ -6,7 +6,7 @@ use base_db::CrateId;
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
name::{AsName, Name},
|
||||
InFile,
|
||||
HirFileId, InFile,
|
||||
};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use syntax::ast::{self, HasName, HasVisibility};
|
||||
@ -17,13 +17,15 @@ use crate::{
|
||||
builtin_type::{BuiltinInt, BuiltinUint},
|
||||
db::DefDatabase,
|
||||
intern::Interned,
|
||||
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||
nameres::diagnostics::DefDiagnostic,
|
||||
src::HasChildSource,
|
||||
src::HasSource,
|
||||
trace::Trace,
|
||||
type_ref::TypeRef,
|
||||
visibility::RawVisibility,
|
||||
EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
|
||||
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
|
||||
VariantId,
|
||||
};
|
||||
use cfg::CfgOptions;
|
||||
|
||||
@ -143,6 +145,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
|
||||
|
||||
impl StructData {
|
||||
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
|
||||
db.struct_data_with_diagnostics(id).0
|
||||
}
|
||||
|
||||
pub(crate) fn struct_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: StructId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
@ -150,16 +159,35 @@ impl StructData {
|
||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
|
||||
let strukt = &item_tree[loc.id.value];
|
||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
|
||||
Arc::new(StructData {
|
||||
name: strukt.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
})
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&strukt.fields,
|
||||
None,
|
||||
);
|
||||
(
|
||||
Arc::new(StructData {
|
||||
name: strukt.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
|
||||
db.union_data_with_diagnostics(id).0
|
||||
}
|
||||
|
||||
pub(crate) fn union_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: UnionId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
@ -167,19 +195,37 @@ impl StructData {
|
||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
|
||||
let union = &item_tree[loc.id.value];
|
||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
|
||||
|
||||
Arc::new(StructData {
|
||||
name: union.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
})
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&union.fields,
|
||||
None,
|
||||
);
|
||||
(
|
||||
Arc::new(StructData {
|
||||
name: union.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EnumData {
|
||||
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
|
||||
db.enum_data_with_diagnostics(e).0
|
||||
}
|
||||
|
||||
pub(crate) fn enum_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
e: EnumId,
|
||||
) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = e.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
@ -188,31 +234,46 @@ impl EnumData {
|
||||
|
||||
let enum_ = &item_tree[loc.id.value];
|
||||
let mut variants = Arena::new();
|
||||
let mut diagnostics = Vec::new();
|
||||
for tree_id in enum_.variants.clone() {
|
||||
if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
|
||||
let var = &item_tree[tree_id];
|
||||
let var_data = lower_fields(
|
||||
let attrs = item_tree.attrs(db, krate, tree_id.into());
|
||||
let var = &item_tree[tree_id];
|
||||
if attrs.is_cfg_enabled(&cfg_options) {
|
||||
let (var_data, field_diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&var.fields,
|
||||
Some(enum_.visibility),
|
||||
);
|
||||
diagnostics.extend(field_diagnostics);
|
||||
|
||||
variants.alloc(EnumVariantData {
|
||||
name: var.name.clone(),
|
||||
variant_data: Arc::new(var_data),
|
||||
});
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
loc.container.local_id,
|
||||
InFile::new(loc.id.file_id(), var.ast_id.upcast()),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Arc::new(EnumData {
|
||||
name: enum_.name.clone(),
|
||||
variants,
|
||||
repr,
|
||||
visibility: item_tree[enum_.visibility].clone(),
|
||||
})
|
||||
(
|
||||
Arc::new(EnumData {
|
||||
name: enum_.name.clone(),
|
||||
variants,
|
||||
repr,
|
||||
visibility: item_tree[enum_.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
||||
@ -384,31 +445,64 @@ fn lower_struct(
|
||||
fn lower_fields(
|
||||
db: &dyn DefDatabase,
|
||||
krate: CrateId,
|
||||
current_file_id: HirFileId,
|
||||
container: LocalModuleId,
|
||||
item_tree: &ItemTree,
|
||||
cfg_options: &CfgOptions,
|
||||
fields: &Fields,
|
||||
override_visibility: Option<RawVisibilityId>,
|
||||
) -> VariantData {
|
||||
) -> (VariantData, Vec<DefDiagnostic>) {
|
||||
let mut diagnostics = Vec::new();
|
||||
match fields {
|
||||
Fields::Record(flds) => {
|
||||
let mut arena = Arena::new();
|
||||
for field_id in flds.clone() {
|
||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
||||
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||
let field = &item_tree[field_id];
|
||||
if attrs.is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, field, override_visibility));
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
container,
|
||||
InFile::new(
|
||||
current_file_id,
|
||||
match field.ast_id {
|
||||
FieldAstId::Record(it) => it.upcast(),
|
||||
FieldAstId::Tuple(it) => it.upcast(),
|
||||
},
|
||||
),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
VariantData::Record(arena)
|
||||
(VariantData::Record(arena), diagnostics)
|
||||
}
|
||||
Fields::Tuple(flds) => {
|
||||
let mut arena = Arena::new();
|
||||
for field_id in flds.clone() {
|
||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
||||
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||
let field = &item_tree[field_id];
|
||||
if attrs.is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, field, override_visibility));
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
container,
|
||||
InFile::new(
|
||||
current_file_id,
|
||||
match field.ast_id {
|
||||
FieldAstId::Record(it) => it.upcast(),
|
||||
FieldAstId::Tuple(it) => it.upcast(),
|
||||
},
|
||||
),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
VariantData::Tuple(arena)
|
||||
(VariantData::Tuple(arena), diagnostics)
|
||||
}
|
||||
Fields::Unit => VariantData::Unit,
|
||||
Fields::Unit => (VariantData::Unit, diagnostics),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ impl TraitData {
|
||||
pub(crate) fn trait_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
tr: TraitId,
|
||||
) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
|
||||
) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) {
|
||||
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
|
||||
let item_tree = tree_id.item_tree(db);
|
||||
let tr_def = &item_tree[tree_id.value];
|
||||
@ -251,7 +251,7 @@ impl TraitData {
|
||||
visibility,
|
||||
skip_array_during_method_dispatch,
|
||||
}),
|
||||
Arc::new(diagnostics),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ impl ImplData {
|
||||
pub(crate) fn impl_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: ImplId,
|
||||
) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
|
||||
) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) {
|
||||
let _p = profile::span("impl_data_with_diagnostics_query");
|
||||
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
|
||||
|
||||
@ -318,7 +318,7 @@ impl ImplData {
|
||||
|
||||
(
|
||||
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
|
||||
Arc::new(diagnostics),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -97,24 +97,33 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
|
||||
#[salsa::invoke(StructData::struct_data_query)]
|
||||
fn struct_data(&self, id: StructId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
|
||||
fn struct_data_with_diagnostics(&self, id: StructId)
|
||||
-> (Arc<StructData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(StructData::union_data_query)]
|
||||
fn union_data(&self, id: UnionId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::union_data_with_diagnostics_query)]
|
||||
fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_query)]
|
||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
|
||||
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(ImplData::impl_data_query)]
|
||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||
|
||||
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
|
||||
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);
|
||||
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(TraitData::trait_data_query)]
|
||||
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
|
||||
|
||||
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
|
||||
fn trait_data_with_diagnostics(&self, tr: TraitId)
|
||||
-> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);
|
||||
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
|
||||
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
|
||||
|
@ -943,6 +943,7 @@ impl AssocItem {
|
||||
pub struct Variant {
|
||||
pub name: Name,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::Variant>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -952,10 +953,17 @@ pub enum Fields {
|
||||
Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum FieldAstId {
|
||||
Record(FileAstId<ast::RecordField>),
|
||||
Tuple(FileAstId<ast::TupleField>),
|
||||
}
|
||||
|
||||
/// A single field of an enum variant or struct
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Field {
|
||||
pub name: Name,
|
||||
pub type_ref: Interned<TypeRef>,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FieldAstId,
|
||||
}
|
||||
|
@ -184,7 +184,8 @@ impl<'a> Ctx<'a> {
|
||||
let name = field.name()?.as_name();
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
let res = Field { name, type_ref, visibility };
|
||||
let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
|
||||
let res = Field { name, type_ref, visibility, ast_id };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
@ -203,7 +204,8 @@ impl<'a> Ctx<'a> {
|
||||
let name = Name::new_tuple_field(idx);
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
Field { name, type_ref, visibility }
|
||||
let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
|
||||
Field { name, type_ref, visibility, ast_id }
|
||||
}
|
||||
|
||||
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
|
||||
@ -247,7 +249,8 @@ impl<'a> Ctx<'a> {
|
||||
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
||||
let name = variant.name()?.as_name();
|
||||
let fields = self.lower_fields(&variant.kind());
|
||||
let res = Variant { name, fields };
|
||||
let ast_id = self.source_ast_id_map.ast_id(variant);
|
||||
let res = Variant { name, fields, ast_id };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ impl<'a> Printer<'a> {
|
||||
w!(self, "{{");
|
||||
self.indented(|this| {
|
||||
for field in fields.clone() {
|
||||
let Field { visibility, name, type_ref } = &this.tree[field];
|
||||
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
|
||||
this.print_attrs_of(field);
|
||||
this.print_visibility(*visibility);
|
||||
w!(this, "{}: ", name);
|
||||
@ -129,7 +129,7 @@ impl<'a> Printer<'a> {
|
||||
w!(self, "(");
|
||||
self.indented(|this| {
|
||||
for field in fields.clone() {
|
||||
let Field { visibility, name, type_ref } = &this.tree[field];
|
||||
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
|
||||
this.print_attrs_of(field);
|
||||
this.print_visibility(*visibility);
|
||||
w!(this, "{}: ", name);
|
||||
@ -323,7 +323,7 @@ impl<'a> Printer<'a> {
|
||||
self.print_where_clause_and_opening_brace(generic_params);
|
||||
self.indented(|this| {
|
||||
for variant in variants.clone() {
|
||||
let Variant { name, fields } = &this.tree[variant];
|
||||
let Variant { name, fields, ast_id: _ } = &this.tree[variant];
|
||||
this.print_attrs_of(variant);
|
||||
w!(this, "{}", name);
|
||||
this.print_fields(fields);
|
||||
|
@ -2122,7 +2122,7 @@ impl ModCollector<'_, '_> {
|
||||
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
|
||||
let ast_id = item.ast_id(self.item_tree);
|
||||
|
||||
let ast_id = InFile::new(self.file_id(), ast_id);
|
||||
let ast_id = InFile::new(self.file_id(), ast_id.upcast());
|
||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
self.module_id,
|
||||
ast_id,
|
||||
|
@ -4,7 +4,7 @@ use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::MacroCallKind;
|
||||
use la_arena::Idx;
|
||||
use syntax::ast;
|
||||
use syntax::ast::{self, AnyHasAttrs};
|
||||
|
||||
use crate::{
|
||||
attr::AttrId,
|
||||
@ -22,7 +22,7 @@ pub enum DefDiagnosticKind {
|
||||
|
||||
UnresolvedImport { id: ItemTreeId<item_tree::Import>, index: Idx<ast::UseTree> },
|
||||
|
||||
UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
|
||||
UnconfiguredCode { ast: AstId<AnyHasAttrs>, cfg: CfgExpr, opts: CfgOptions },
|
||||
|
||||
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
|
||||
|
||||
@ -75,7 +75,7 @@ impl DefDiagnostic {
|
||||
|
||||
pub fn unconfigured_code(
|
||||
container: LocalModuleId,
|
||||
ast: AstId<ast::Item>,
|
||||
ast: AstId<ast::AnyHasAttrs>,
|
||||
cfg: CfgExpr,
|
||||
opts: CfgOptions,
|
||||
) -> Self {
|
||||
|
@ -93,7 +93,12 @@ impl AstIdMap {
|
||||
// trait does not change ids of top-level items, which helps caching.
|
||||
bdfs(node, |it| {
|
||||
let kind = it.kind();
|
||||
if ast::Item::can_cast(kind) || ast::BlockExpr::can_cast(kind) {
|
||||
if ast::Item::can_cast(kind)
|
||||
|| ast::BlockExpr::can_cast(kind)
|
||||
|| ast::Variant::can_cast(kind)
|
||||
|| ast::RecordField::can_cast(kind)
|
||||
|| ast::TupleField::can_cast(kind)
|
||||
{
|
||||
res.alloc(&it);
|
||||
true
|
||||
} else {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Re-export diagnostics such that clients of `hir` don't have to depend on
|
||||
//! low-level crates.
|
||||
//!
|
||||
//! This probably isn't the best way to do this -- ideally, diagnistics should
|
||||
//! This probably isn't the best way to do this -- ideally, diagnostics should
|
||||
//! be expressed in terms of hir types themselves.
|
||||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
|
@ -540,9 +540,27 @@ impl Module {
|
||||
}
|
||||
acc.extend(decl.diagnostics(db))
|
||||
}
|
||||
ModuleDef::Adt(Adt::Enum(e)) => {
|
||||
for v in e.variants(db) {
|
||||
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
||||
ModuleDef::Adt(adt) => {
|
||||
match adt {
|
||||
Adt::Struct(s) => {
|
||||
for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
|
||||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
}
|
||||
Adt::Union(u) => {
|
||||
for diag in db.union_data_with_diagnostics(u.id).1.iter() {
|
||||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
}
|
||||
Adt::Enum(e) => {
|
||||
for v in e.variants(db) {
|
||||
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
||||
}
|
||||
|
||||
for diag in db.enum_data_with_diagnostics(e.id).1.iter() {
|
||||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.extend(decl.diagnostics(db))
|
||||
}
|
||||
|
@ -137,6 +137,37 @@ trait Bar {
|
||||
|
||||
#[cfg_attr(not(never), inline, cfg(no))] fn h() {}
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: no is disabled
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inactive_fields_and_variants() {
|
||||
check(
|
||||
r#"
|
||||
enum Foo {
|
||||
#[cfg(a)] Bar,
|
||||
//^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
Baz {
|
||||
#[cfg(a)] baz: String,
|
||||
//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
},
|
||||
Qux(#[cfg(a)] String),
|
||||
//^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
}
|
||||
|
||||
struct Baz {
|
||||
#[cfg(a)] baz: String,
|
||||
//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
}
|
||||
|
||||
struct Qux(#[cfg(a)] String);
|
||||
//^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
|
||||
union FooBar {
|
||||
#[cfg(a)] baz: u32,
|
||||
//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -873,3 +873,33 @@ impl ast::MatchGuard {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::Item> for ast::AnyHasAttrs {
|
||||
fn from(node: ast::Item) -> Self {
|
||||
Self::new(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::AssocItem> for ast::AnyHasAttrs {
|
||||
fn from(node: ast::AssocItem) -> Self {
|
||||
Self::new(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::Variant> for ast::AnyHasAttrs {
|
||||
fn from(node: ast::Variant) -> Self {
|
||||
Self::new(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::RecordField> for ast::AnyHasAttrs {
|
||||
fn from(node: ast::RecordField) -> Self {
|
||||
Self::new(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::TupleField> for ast::AnyHasAttrs {
|
||||
fn from(node: ast::TupleField) -> Self {
|
||||
Self::new(node)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user