Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix multi forbids #57

Merged
merged 2 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions geiger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ maintenance = { status = "experimental" }
[dependencies]
syn = { version = "0.15.34", features = ["parsing", "printing", "clone-impls", "full", "extra-traits", "visit"] }
walkdir = "2.2.7"
proc-macro2 = "0.4.30"
54 changes: 39 additions & 15 deletions geiger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#![forbid(unsafe_code)]
#![forbid(warnings)]

extern crate proc_macro2;
extern crate syn;
extern crate walkdir;

Expand Down Expand Up @@ -127,25 +128,14 @@ struct GeigerSynVisitor {

/// Used by the Visit trait implementation to track the traversal state.
in_unsafe_block: bool,

forbid_unsafe_code_attribute: syn::Attribute,
}

impl GeigerSynVisitor {
fn new(include_tests: IncludeTests) -> Self {
// TODO: Use lazy static?
let code = "#![forbid(unsafe_code)]";
let forbid_unsafe_code_attribute = match syn::parse_file(code) {
Ok(file) => file.attrs[0].clone(),
Err(e) => {
panic!("Failed to parse hard-coded literal: {}, {}", code, e)
}
};
GeigerSynVisitor {
include_tests,
metrics: Default::default(),
in_unsafe_block: false,
forbid_unsafe_code_attribute,
}
}
}
Expand Down Expand Up @@ -209,12 +199,46 @@ fn is_test_fn(i: &ItemFn) -> bool {
.any(|m| meta_is_word_test(&m))
}

fn file_forbids_unsafe(f: &syn::File) -> bool {
use proc_macro2::{Ident, Span};
use syn::AttrStyle;
use syn::Meta;
use syn::MetaList;
use syn::NestedMeta;
let forbid_ident = Ident::new("forbid", Span::call_site());
let unsafe_code_ident = Ident::new("unsafe_code", Span::call_site());
f.attrs
.iter()
.filter(|a| match a.style {
AttrStyle::Inner(_) => true,
_ => false,
})
.filter_map(|a| a.parse_meta().ok())
.filter(|meta| match meta {
Meta::List(MetaList {
ident,
paren_token: _paren,
nested,
}) => {
if ident != &forbid_ident {
return false;
}
nested.iter().any(|n| match n {
NestedMeta::Meta(Meta::Word(word)) => {
word == &unsafe_code_ident
}
_ => false,
})
}
_ => false,
})
.count()
> 0
}

impl<'ast> visit::Visit<'ast> for GeigerSynVisitor {
fn visit_file(&mut self, i: &'ast syn::File) {
self.metrics.forbids_unsafe = i
.attrs
.iter()
.any(|a| a == &self.forbid_unsafe_code_attribute);
self.metrics.forbids_unsafe = file_forbids_unsafe(i);
syn::visit::visit_file(self, i);
}

Expand Down