#![feature(plugin, rustc_private)] #![crate_type = "dylib"] extern crate rustc_ast_pretty; extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_lint; #[macro_use] extern crate rustc_session; extern crate rustc_ast; extern crate rustc_span; use rustc_ast_pretty::pprust; use rustc_driver::plugin::Registry; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_hir::Node; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map; #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]); reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass)); } declare_lint! { MISSING_ALLOWED_ATTR, Deny, "Checks for missing `allowed_attr` attribute" } declare_lint_pass!(MissingAllowedAttrPass => [MISSING_ALLOWED_ATTR]); impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass { fn check_fn( &mut self, cx: &LateContext<'tcx>, _: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl, _: &'tcx hir::Body, span: source_map::Span, def_id: LocalDefId, ) { let id = cx.tcx.hir().local_def_id_to_hir_id(def_id); let item = match cx.tcx.hir().get(id) { Node::Item(item) => item, _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id), }; let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) { cx.lint( MISSING_ALLOWED_ATTR, "Missing 'allowed_attr' attribute", |lint| lint.set_span(span) ); } } }