#![forbid(unsafe_code)]
#![deny(warnings)]
pub mod find;
pub use find::*;
mod geiger_syn_visitor;
use cargo_geiger_serde::CounterBlock;
use std::error::Error;
use std::fmt;
use std::io;
use std::path::PathBuf;
use std::string::FromUtf8Error;
use syn::{AttrStyle, ItemFn, ItemMod};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum IncludeTests {
Yes,
No,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RsFileMetrics {
pub counters: CounterBlock,
pub forbids_unsafe: bool,
}
#[derive(Debug)]
pub enum ScanFileError {
Io(io::Error, PathBuf),
Utf8(FromUtf8Error, PathBuf),
Syn(syn::Error, PathBuf),
}
impl Error for ScanFileError {}
impl fmt::Display for ScanFileError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
fn file_forbids_unsafe(f: &syn::File) -> bool {
f.attrs.iter().any(|attr| {
let mut is_forbid_unsafe_code = false;
if matches!(attr.style, AttrStyle::Inner(_)) {
if attr.path().is_ident("forbid") {
let _ = attr.parse_nested_meta(|meta| {
if meta.path.is_ident("unsafe_code") {
if meta.value().is_err() {
is_forbid_unsafe_code = true;
}
}
Ok(())
});
}
}
is_forbid_unsafe_code
})
}
fn is_test_fn(item_fn: &ItemFn) -> bool {
item_fn
.attrs
.iter()
.any(|attr| attr.path().is_ident("test"))
}
fn has_unsafe_attributes(item_fn: &ItemFn) -> bool {
item_fn.attrs.iter().any(|attr| {
if attr.path().is_ident("no_mangle") {
return true;
}
if attr.path().is_ident("export_name") {
return true;
}
false
})
}
fn is_test_mod(item: &ItemMod) -> bool {
item.attrs.iter().any(|attr| {
let mut found_cfg_test = false;
if attr.path().is_ident("cfg") {
let _ = attr.parse_nested_meta(|meta| {
if meta.path.is_ident("test") {
found_cfg_test = true;
}
Ok(())
});
}
found_cfg_test
})
}