Skip to content

Commit

Permalink
feat(print): print location of use std:: statements
Browse files Browse the repository at this point in the history
REFERENCE #10
  • Loading branch information
hobofan committed Jan 17, 2019
1 parent c09cf98 commit a13cc45
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 15 deletions.
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ serde = "1.0.80"
serde_json = "1.0.33"
console = "0.6.2"
syn = { version = "=0.15.18", default-features = false, features = ["full", "extra-traits", "parsing"] }
quote = "0.6.10"
quote = { version = "0.6.10", default-features = false }
clap = "2.32.0"
proc-macro2 = "0.4.24"
proc-macro2 = { version = "0.4.24", default-features = false }

[dev-dependencies]
assert_cmd = "0.10.2"

[features]
default = []
proc_macro_spans = []
6 changes: 6 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
match std::env::var("CARGO_CFG_PROCMACRO2_SEMVER_EXEMPT") {
Ok(_) => println!("cargo:rustc-cfg=feature=\"proc_macro_spans\""),
Err(_) => {}
}
}
94 changes: 83 additions & 11 deletions src/check.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use proc_macro2;
use proc_macro2::TokenTree;
use quote::quote;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use syn::spanned::Spanned;

#[cfg(feature = "proc_macro_spans")]
use std::io::BufRead;

use ext::*;

Expand Down Expand Up @@ -90,7 +95,70 @@ pub enum SourceOffense {
/// Only valid for entry point file (main.rs / lib.rs).
MissingNoStdAttribute,
/// Source code contains an explicit `use std::` statement.
UseStdStatement,
UseStdStatement(UseStdStmt),
}

#[derive(Debug)]
pub struct UseStdStmt {
src_path: PathBuf,
span: proc_macro2::Span,
}

impl PartialEq for UseStdStmt {
fn eq(&self, other: &UseStdStmt) -> bool {
self.src_path == other.src_path
}
}
impl Eq for UseStdStmt {}

#[cfg(feature = "proc_macro_spans")]
impl fmt::Display for UseStdStmt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let file = File::open(&self.src_path).unwrap();
let file = std::io::BufReader::new(file);
let line = file
.lines()
.skip(self.span.start().line - 1)
.next()
.unwrap()
.unwrap();

writeln!(
f,
" --> {src}:{line}:{column}",
src = self
.src_path
.strip_prefix(std::env::current_dir().unwrap())
.unwrap()
.display(),
line = self.span.start().line,
column = self.span.start().column
)?;
writeln!(f, " |")?;

writeln!(
f,
"{line_num:<4}|{line}",
line_num = self.span.start().line,
line = line
)?;
writeln!(f, " |")
}
}

#[cfg(not(feature = "proc_macro_spans"))]
impl fmt::Display for UseStdStmt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
" --> {src}",
src = self
.src_path
.strip_prefix(std::env::current_dir().unwrap())
.unwrap()
.display(),
)
}
}

pub fn get_crate_support_from_source(src_path: &PathBuf) -> CrateSupport {
Expand All @@ -116,27 +184,31 @@ pub fn get_crate_support_from_source(src_path: &PathBuf) -> CrateSupport {

let mut offenses = vec![];

let use_statements: Vec<_> = syntax.items.iter().filter_map(|item| match item {
syn::Item::Use(item) => Some(item),
_ => None,
}).collect();
let use_statements: Vec<_> = syntax
.items
.iter()
.filter_map(|item| match item {
syn::Item::Use(item) => Some(item),
_ => None,
})
.collect();

let mut has_use_std = false;
let std_ident: syn::Ident = syn::parse_quote!(std);
for use_statement in &use_statements {
match use_statement.tree {
syn::UseTree::Path(ref first_path) => {
let first_ident = &first_path.ident;
if first_ident == &std_ident {
has_use_std = true;
let stmt = UseStdStmt {
src_path: src_path.clone(),
span: use_statement.tree.span(),
};
offenses.push(SourceOffense::UseStdStatement(stmt));
}
},
}
_ => unimplemented!(),
}
}
if has_use_std {
offenses.push(SourceOffense::UseStdStatement);
}

let always_no_std: syn::Attribute = syn::parse_quote!(#![no_std]);
let contains_always_no_std = syntax.attrs.contains(&always_no_std);
Expand Down
5 changes: 3 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ fn check_and_print_package(
match offense {
SourceOffense::MissingNoStdAttribute => {
println!(" - Did not find a #![no_std] attribute or a simple conditional attribute like #[cfg_attr(not(feature = \"std\"), no_std)] in the crate source. Crate most likely doesn't support no_std without changes.");
},
SourceOffense::UseStdStatement => {
}
SourceOffense::UseStdStatement(stmt) => {
println!(" - Source code contains an explicit `use std::` statement.");
println!("{}", stmt);
}
}
}
Expand Down

0 comments on commit a13cc45

Please sign in to comment.