Skip to content

Instantly share code, notes, and snippets.

@durka
Last active August 27, 2015 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save durka/a5243440697c780f669b to your computer and use it in GitHub Desktop.
Save durka/a5243440697c780f669b to your computer and use it in GitHub Desktop.
Script for finding bad unstable feature annotations
# run this first
# dependencies: httpie, ag (the silver searcher)
for issue in $(ag -o 'issue.*?=.*?".*?"' src/ | awk -F\" '{print $2}' | grep -v '^0$' | sort | uniq)
do
echo $issue
http https://github.com/rust-lang/rust/issues/$issue > $issue.txt
done
// run cache_issues.sh first
// dependencies: none
use std::io::{self, Read, BufRead, BufReader};
use std::fs::{self, File, DirEntry};
use std::path::Path;
// copied from the fs::read_dir docs
fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
if try!(fs::metadata(dir)).is_dir() {
for entry in try!(fs::read_dir(dir)) {
let entry = try!(entry);
if try!(fs::metadata(entry.path())).is_dir() {
try!(visit_dirs(&entry.path(), cb));
} else {
cb(&entry);
}
}
}
Ok(())
}
fn main() {
// recursively walk src/
visit_dirs(&Path::new("src"), &|entry| {
let file = String::from(entry.path().to_str().unwrap());
// only parse the file if it's Rust and it isn't a compile-fail test
if file.ends_with(".rs") && !file.contains("/compile-fail/") {
let mut lines = BufReader::new(File::open(entry.path()).unwrap()).lines();
// loop over the lines of the file
// this isn't a normal for-loop because I might need to skip some lines during the loop
loop {
let maybe_line = lines.next(); // check for EOF
match maybe_line {
// the file is still going!
Some(line) => {
// we are going to build up the #[unstable(...)] clause, if there is one
// starting on this line
// NB: they can start and end in the middle of lines (with more than just
// whitespace on either side), and they can span multiple lines
let foo = line.unwrap(); let mut line = String::from(foo.trim());
let mut unstable_clause = String::from("");
if let Some(i) = line.find("#[unstable(") { // here we go!
unstable_clause = unstable_clause + &line[i..];
// in the case of a multi-line #[unstable(...)] clause, this loop finds
// the end of it
loop {
if let Some(i) = line.rfind(")]") {
unstable_clause = unstable_clause + &line[..i];
break;
} else {
let foo = lines.next().unwrap().unwrap(); line = String::from(foo.trim());
unstable_clause = unstable_clause + &line;
}
}
// chop off the "#[unstable(" and the ")]"
unstable_clause = {
let unstable_chars = unstable_clause.chars();
let unstable_skip = unstable_chars.skip("#[unstable(".len());
let n = unstable_skip.size_hint().1.unwrap() - 2;
let unstable_take = unstable_skip.take(n);
unstable_take.collect()
};
// now extract the feature name and the issue number (don't care about
// the reason string), and report possible problems
let unstable_parts = unstable_clause.split(",");
let feature = unstable_parts.clone().find(|x| x.trim_left().starts_with("feature")).unwrap().split("\"").nth(1).unwrap();
if let Some(issue) = unstable_parts.clone().find(|x| x.trim_left().starts_with("issue")) {
let issue = issue.split("\"").nth(1).unwrap();
if issue == "0" {
println!("Feature with issue ref of 0! {} {}", file, feature);
} else {
let mut html = String::from("");
File::open(format!("{}.txt", issue)).unwrap().read_to_string(&mut html).unwrap();
if !html.contains(feature) {
println!("Feature with possibly wrong issue ref! {} {} {}", file, feature, issue);
}
}
} else {
println!("Feature with no issue ref! {} {}", file, feature);
}
}
},
// no more lines -- goodbye
None => break
}
}
}
}).unwrap();
}
[this file sets the title of the gist]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment