mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +00:00
Collect diagnostics in queries instead of nameres
This commit is contained in:
parent
89107d5469
commit
b21bf25a07
5 changed files with 194 additions and 116 deletions
|
@ -6,7 +6,7 @@ use base_db::CrateId;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
InFile,
|
HirFileId, InFile,
|
||||||
};
|
};
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::{Arena, ArenaMap};
|
||||||
use syntax::ast::{self, HasName, HasVisibility};
|
use syntax::ast::{self, HasName, HasVisibility};
|
||||||
|
@ -17,13 +17,15 @@ use crate::{
|
||||||
builtin_type::{BuiltinInt, BuiltinUint},
|
builtin_type::{BuiltinInt, BuiltinUint},
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
intern::Interned,
|
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::HasChildSource,
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
trace::Trace,
|
trace::Trace,
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
visibility::RawVisibility,
|
visibility::RawVisibility,
|
||||||
EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
|
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
|
||||||
|
VariantId,
|
||||||
};
|
};
|
||||||
use cfg::CfgOptions;
|
use cfg::CfgOptions;
|
||||||
|
|
||||||
|
@ -143,6 +145,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
|
||||||
|
|
||||||
impl StructData {
|
impl StructData {
|
||||||
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<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<Vec<DefDiagnostic>>) {
|
||||||
let loc = id.lookup(db);
|
let loc = id.lookup(db);
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
let item_tree = loc.id.item_tree(db);
|
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 cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||||
|
|
||||||
let strukt = &item_tree[loc.id.value];
|
let strukt = &item_tree[loc.id.value];
|
||||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
|
let (variant_data, diagnostics) = lower_fields(
|
||||||
Arc::new(StructData {
|
db,
|
||||||
name: strukt.name.clone(),
|
krate,
|
||||||
variant_data: Arc::new(variant_data),
|
loc.id.file_id(),
|
||||||
repr,
|
loc.container.local_id,
|
||||||
visibility: item_tree[strukt.visibility].clone(),
|
&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(),
|
||||||
|
}),
|
||||||
|
Arc::new(diagnostics),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
|
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<Vec<DefDiagnostic>>) {
|
||||||
let loc = id.lookup(db);
|
let loc = id.lookup(db);
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
let item_tree = loc.id.item_tree(db);
|
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 cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||||
|
|
||||||
let union = &item_tree[loc.id.value];
|
let union = &item_tree[loc.id.value];
|
||||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
|
let (variant_data, diagnostics) = lower_fields(
|
||||||
|
db,
|
||||||
Arc::new(StructData {
|
krate,
|
||||||
name: union.name.clone(),
|
loc.id.file_id(),
|
||||||
variant_data: Arc::new(variant_data),
|
loc.container.local_id,
|
||||||
repr,
|
&item_tree,
|
||||||
visibility: item_tree[union.visibility].clone(),
|
&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(),
|
||||||
|
}),
|
||||||
|
Arc::new(diagnostics),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumData {
|
impl EnumData {
|
||||||
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<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<Vec<DefDiagnostic>>) {
|
||||||
let loc = e.lookup(db);
|
let loc = e.lookup(db);
|
||||||
let krate = loc.container.krate;
|
let krate = loc.container.krate;
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
|
@ -188,31 +234,46 @@ impl EnumData {
|
||||||
|
|
||||||
let enum_ = &item_tree[loc.id.value];
|
let enum_ = &item_tree[loc.id.value];
|
||||||
let mut variants = Arena::new();
|
let mut variants = Arena::new();
|
||||||
|
let mut diagnostics = Vec::new();
|
||||||
for tree_id in enum_.variants.clone() {
|
for tree_id in enum_.variants.clone() {
|
||||||
if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
|
let attrs = item_tree.attrs(db, krate, tree_id.into());
|
||||||
let var = &item_tree[tree_id];
|
let var = &item_tree[tree_id];
|
||||||
let var_data = lower_fields(
|
if attrs.is_cfg_enabled(&cfg_options) {
|
||||||
|
let (var_data, field_diagnostics) = lower_fields(
|
||||||
db,
|
db,
|
||||||
krate,
|
krate,
|
||||||
|
loc.id.file_id(),
|
||||||
|
loc.container.local_id,
|
||||||
&item_tree,
|
&item_tree,
|
||||||
&cfg_options,
|
&cfg_options,
|
||||||
&var.fields,
|
&var.fields,
|
||||||
Some(enum_.visibility),
|
Some(enum_.visibility),
|
||||||
);
|
);
|
||||||
|
diagnostics.extend(field_diagnostics);
|
||||||
|
|
||||||
variants.alloc(EnumVariantData {
|
variants.alloc(EnumVariantData {
|
||||||
name: var.name.clone(),
|
name: var.name.clone(),
|
||||||
variant_data: Arc::new(var_data),
|
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(),
|
Arc::new(EnumData {
|
||||||
variants,
|
name: enum_.name.clone(),
|
||||||
repr,
|
variants,
|
||||||
visibility: item_tree[enum_.visibility].clone(),
|
repr,
|
||||||
})
|
visibility: item_tree[enum_.visibility].clone(),
|
||||||
|
}),
|
||||||
|
Arc::new(diagnostics),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
||||||
|
@ -384,31 +445,64 @@ fn lower_struct(
|
||||||
fn lower_fields(
|
fn lower_fields(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
|
current_file_id: HirFileId,
|
||||||
|
container: LocalModuleId,
|
||||||
item_tree: &ItemTree,
|
item_tree: &ItemTree,
|
||||||
cfg_options: &CfgOptions,
|
cfg_options: &CfgOptions,
|
||||||
fields: &Fields,
|
fields: &Fields,
|
||||||
override_visibility: Option<RawVisibilityId>,
|
override_visibility: Option<RawVisibilityId>,
|
||||||
) -> VariantData {
|
) -> (VariantData, Vec<DefDiagnostic>) {
|
||||||
|
let mut diagnostics = Vec::new();
|
||||||
match fields {
|
match fields {
|
||||||
Fields::Record(flds) => {
|
Fields::Record(flds) => {
|
||||||
let mut arena = Arena::new();
|
let mut arena = Arena::new();
|
||||||
for field_id in flds.clone() {
|
for field_id in flds.clone() {
|
||||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
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) => {
|
Fields::Tuple(flds) => {
|
||||||
let mut arena = Arena::new();
|
let mut arena = Arena::new();
|
||||||
for field_id in flds.clone() {
|
for field_id in flds.clone() {
|
||||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,12 +97,27 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
|
||||||
#[salsa::invoke(StructData::struct_data_query)]
|
#[salsa::invoke(StructData::struct_data_query)]
|
||||||
fn struct_data(&self, id: StructId) -> Arc<StructData>;
|
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<Vec<DefDiagnostic>>);
|
||||||
|
|
||||||
#[salsa::invoke(StructData::union_data_query)]
|
#[salsa::invoke(StructData::union_data_query)]
|
||||||
fn union_data(&self, id: UnionId) -> Arc<StructData>;
|
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<Vec<DefDiagnostic>>);
|
||||||
|
|
||||||
#[salsa::invoke(EnumData::enum_data_query)]
|
#[salsa::invoke(EnumData::enum_data_query)]
|
||||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
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<Vec<DefDiagnostic>>);
|
||||||
|
|
||||||
#[salsa::invoke(ImplData::impl_data_query)]
|
#[salsa::invoke(ImplData::impl_data_query)]
|
||||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ use crate::{
|
||||||
derive_macro_as_call_id,
|
derive_macro_as_call_id,
|
||||||
item_scope::{ImportType, PerNsGlobImports},
|
item_scope::{ImportType, PerNsGlobImports},
|
||||||
item_tree::{
|
item_tree::{
|
||||||
self, FieldAstId, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
|
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
|
||||||
MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
|
MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||||
},
|
},
|
||||||
macro_call_as_call_id, macro_id_to_def_id,
|
macro_call_as_call_id, macro_id_to_def_id,
|
||||||
nameres::{
|
nameres::{
|
||||||
|
@ -1511,10 +1511,7 @@ impl ModCollector<'_, '_> {
|
||||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
|
let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
|
||||||
if let Some(cfg) = attrs.cfg() {
|
if let Some(cfg) = attrs.cfg() {
|
||||||
if !self.is_cfg_enabled(&cfg) {
|
if !self.is_cfg_enabled(&cfg) {
|
||||||
self.emit_unconfigured_diagnostic(
|
self.emit_unconfigured_diagnostic(item, &cfg);
|
||||||
InFile::new(self.file_id(), item.ast_id(&self.item_tree).upcast()),
|
|
||||||
&cfg,
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1526,20 +1523,22 @@ impl ModCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = self.def_collector.db;
|
let db = self.def_collector.db;
|
||||||
let module_id = self.module_id;
|
let module = self.def_collector.def_map.module_id(self.module_id);
|
||||||
let module = self.def_collector.def_map.module_id(module_id);
|
let def_map = &mut self.def_collector.def_map;
|
||||||
let update_def =
|
let update_def =
|
||||||
|def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
|
|def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
|
||||||
def_collector.def_map.modules[module_id].scope.declare(id);
|
def_collector.def_map.modules[self.module_id].scope.declare(id);
|
||||||
def_collector.update(
|
def_collector.update(
|
||||||
module_id,
|
self.module_id,
|
||||||
&[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
|
&[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
|
||||||
vis,
|
vis,
|
||||||
ImportType::Named,
|
ImportType::Named,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let resolve_vis = |def_map: &DefMap, visibility| {
|
let resolve_vis = |def_map: &DefMap, visibility| {
|
||||||
def_map.resolve_visibility(db, module_id, visibility).unwrap_or(Visibility::Public)
|
def_map
|
||||||
|
.resolve_visibility(db, self.module_id, visibility)
|
||||||
|
.unwrap_or(Visibility::Public)
|
||||||
};
|
};
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
|
@ -1595,7 +1594,6 @@ impl ModCollector<'_, '_> {
|
||||||
let fn_id =
|
let fn_id =
|
||||||
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
|
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
|
||||||
|
|
||||||
let def_map = &self.def_collector.def_map;
|
|
||||||
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
if self.def_collector.is_proc_macro {
|
if self.def_collector.is_proc_macro {
|
||||||
if self.module_id == def_map.root {
|
if self.module_id == def_map.root {
|
||||||
|
@ -1616,10 +1614,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Struct(id) => {
|
ModItem::Struct(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
self.process_fields(&it.fields);
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
|
|
||||||
let vis =
|
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -1633,10 +1628,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Union(id) => {
|
ModItem::Union(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
self.process_fields(&it.fields);
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
|
|
||||||
let vis =
|
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -1650,21 +1642,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Enum(id) => {
|
ModItem::Enum(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
for id in it.variants.clone() {
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
let variant = &self.item_tree[id];
|
|
||||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.into());
|
|
||||||
if let Some(cfg) = attrs.cfg() {
|
|
||||||
if !self.is_cfg_enabled(&cfg) {
|
|
||||||
self.emit_unconfigured_diagnostic(
|
|
||||||
InFile::new(self.file_id(), variant.ast_id.upcast()),
|
|
||||||
&cfg,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vis =
|
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -1682,10 +1660,7 @@ impl ModCollector<'_, '_> {
|
||||||
|
|
||||||
match &it.name {
|
match &it.name {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let vis = resolve_vis(
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
&self.def_collector.def_map,
|
|
||||||
&self.item_tree[it.visibility],
|
|
||||||
);
|
|
||||||
update_def(self.def_collector, const_id.into(), name, vis, false);
|
update_def(self.def_collector, const_id.into(), name, vis, false);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -1699,8 +1674,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Static(id) => {
|
ModItem::Static(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
let vis =
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
|
StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -1714,8 +1688,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Trait(id) => {
|
ModItem::Trait(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
let vis =
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -1729,8 +1702,7 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::TypeAlias(id) => {
|
ModItem::TypeAlias(id) => {
|
||||||
let it = &self.item_tree[id];
|
let it = &self.item_tree[id];
|
||||||
|
|
||||||
let vis =
|
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||||
resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
|
|
||||||
update_def(
|
update_def(
|
||||||
self.def_collector,
|
self.def_collector,
|
||||||
TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
|
TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
|
||||||
|
@ -2143,44 +2115,17 @@ impl ModCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_fields(&mut self, fields: &Fields) {
|
|
||||||
match fields {
|
|
||||||
Fields::Record(range) | Fields::Tuple(range) => {
|
|
||||||
for id in range.clone() {
|
|
||||||
let field = &self.item_tree[id];
|
|
||||||
let attrs = self.item_tree.attrs(
|
|
||||||
self.def_collector.db,
|
|
||||||
self.def_collector.def_map.krate,
|
|
||||||
id.into(),
|
|
||||||
);
|
|
||||||
if let Some(cfg) = attrs.cfg() {
|
|
||||||
if !self.is_cfg_enabled(&cfg) {
|
|
||||||
self.emit_unconfigured_diagnostic(
|
|
||||||
InFile::new(
|
|
||||||
self.file_id(),
|
|
||||||
match field.ast_id {
|
|
||||||
FieldAstId::Record(it) => it.upcast(),
|
|
||||||
FieldAstId::Tuple(it) => it.upcast(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
&cfg,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Fields::Unit => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
|
fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
|
||||||
self.def_collector.cfg_options.check(cfg) != Some(false)
|
self.def_collector.cfg_options.check(cfg) != Some(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unconfigured_diagnostic(&mut self, ast: AstId<ast::AnyHasAttrs>, cfg: &CfgExpr) {
|
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.upcast());
|
||||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||||
self.module_id,
|
self.module_id,
|
||||||
ast,
|
ast_id,
|
||||||
cfg.clone(),
|
cfg.clone(),
|
||||||
self.def_collector.cfg_options.clone(),
|
self.def_collector.cfg_options.clone(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -540,9 +540,27 @@ impl Module {
|
||||||
}
|
}
|
||||||
acc.extend(decl.diagnostics(db))
|
acc.extend(decl.diagnostics(db))
|
||||||
}
|
}
|
||||||
ModuleDef::Adt(Adt::Enum(e)) => {
|
ModuleDef::Adt(adt) => {
|
||||||
for v in e.variants(db) {
|
match adt {
|
||||||
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
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))
|
acc.extend(decl.diagnostics(db))
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,12 +142,18 @@ trait Bar {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inactive_fields() {
|
fn inactive_fields_and_variants() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
enum Foo {
|
enum Foo {
|
||||||
#[cfg(a)] Bar,
|
#[cfg(a)] Bar,
|
||||||
//^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
//^^^^^^^^^^^^^ 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 {
|
struct Baz {
|
||||||
|
|
Loading…
Reference in a new issue