2019-12-30 12:02:52 -06:00
|
|
|
use rustc::hir::intravisit;
|
2020-01-07 10:25:33 -06:00
|
|
|
use rustc::hir::map::Map;
|
2019-12-30 12:02:52 -06:00
|
|
|
use rustc::lint::{LintLevelMap, LintLevelSets, LintLevelsBuilder, LintStore};
|
|
|
|
use rustc::ty::query::Providers;
|
|
|
|
use rustc::ty::TyCtxt;
|
2020-01-04 19:37:57 -06:00
|
|
|
use rustc_hir as hir;
|
|
|
|
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
2019-12-30 12:02:52 -06:00
|
|
|
use syntax::ast;
|
|
|
|
|
|
|
|
pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
|
|
|
|
|
|
|
|
fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
|
|
|
|
assert_eq!(cnum, LOCAL_CRATE);
|
|
|
|
let store = &tcx.lint_store;
|
|
|
|
let mut builder = LintLevelMapBuilder {
|
|
|
|
levels: LintLevelSets::builder(tcx.sess, false, &store),
|
|
|
|
tcx: tcx,
|
|
|
|
store: store,
|
|
|
|
};
|
|
|
|
let krate = tcx.hir().krate();
|
|
|
|
|
|
|
|
let push = builder.levels.push(&krate.attrs, &store);
|
|
|
|
builder.levels.register_id(hir::CRATE_HIR_ID);
|
|
|
|
for macro_def in krate.exported_macros {
|
|
|
|
builder.levels.register_id(macro_def.hir_id);
|
|
|
|
}
|
|
|
|
intravisit::walk_crate(&mut builder, krate);
|
|
|
|
builder.levels.pop(push);
|
|
|
|
|
|
|
|
tcx.arena.alloc(builder.levels.build_map())
|
|
|
|
}
|
|
|
|
|
|
|
|
struct LintLevelMapBuilder<'a, 'tcx> {
|
|
|
|
levels: LintLevelsBuilder<'tcx>,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
store: &'a LintStore,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LintLevelMapBuilder<'_, '_> {
|
|
|
|
fn with_lint_attrs<F>(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F)
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut Self),
|
|
|
|
{
|
|
|
|
let push = self.levels.push(attrs, self.store);
|
|
|
|
if push.changed {
|
|
|
|
self.levels.register_id(id);
|
|
|
|
}
|
|
|
|
f(self);
|
|
|
|
self.levels.pop(push);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
|
2020-01-07 10:25:33 -06:00
|
|
|
type Map = Map<'tcx>;
|
|
|
|
|
|
|
|
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
|
2019-12-30 12:02:52 -06:00
|
|
|
intravisit::NestedVisitorMap::All(&self.tcx.hir())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
|
|
|
self.with_lint_attrs(param.hir_id, ¶m.attrs, |builder| {
|
|
|
|
intravisit::walk_param(builder, param);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
|
|
|
|
self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
|
|
|
|
intravisit::walk_item(builder, it);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
|
|
|
|
self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
|
|
|
|
intravisit::walk_foreign_item(builder, it);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
|
|
|
|
self.with_lint_attrs(e.hir_id, &e.attrs, |builder| {
|
|
|
|
intravisit::walk_expr(builder, e);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
|
|
|
|
self.with_lint_attrs(s.hir_id, &s.attrs, |builder| {
|
|
|
|
intravisit::walk_struct_field(builder, s);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_variant(
|
|
|
|
&mut self,
|
|
|
|
v: &'tcx hir::Variant<'tcx>,
|
|
|
|
g: &'tcx hir::Generics<'tcx>,
|
|
|
|
item_id: hir::HirId,
|
|
|
|
) {
|
|
|
|
self.with_lint_attrs(v.id, &v.attrs, |builder| {
|
|
|
|
intravisit::walk_variant(builder, v, g, item_id);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
|
|
|
|
self.with_lint_attrs(l.hir_id, &l.attrs, |builder| {
|
|
|
|
intravisit::walk_local(builder, l);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
|
|
|
|
self.with_lint_attrs(a.hir_id, &a.attrs, |builder| {
|
|
|
|
intravisit::walk_arm(builder, a);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
|
|
|
self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| {
|
|
|
|
intravisit::walk_trait_item(builder, trait_item);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
|
|
|
self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |builder| {
|
|
|
|
intravisit::walk_impl_item(builder, impl_item);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn provide(providers: &mut Providers<'_>) {
|
|
|
|
providers.lint_levels = lint_levels;
|
|
|
|
}
|