--- /dev/null
+use std::collections::HashMap;
+
+#[derive(RustcDecodable, Debug)]
+pub struct Metadata {
+ pub packages: Vec<Package>,
+ resolve: Option<()>,
+ pub version: usize,
+}
+
+#[derive(RustcDecodable, Debug)]
+pub struct Package {
+ name: String,
+ version: String,
+ id: String,
+ source: Option<()>,
+ dependencies: Vec<Dependency>,
+ pub targets: Vec<Target>,
+ features: HashMap<String, Vec<String>>,
+ manifest_path: String,
+}
+
+#[derive(RustcDecodable, Debug)]
+pub struct Dependency {
+ name: String,
+ source: Option<String>,
+ req: String,
+ kind: Option<String>,
+ optional: bool,
+ uses_default_features: bool,
+ features: Vec<HashMap<String, String>>,
+ target: Option<()>,
+}
+
+#[allow(non_camel_case_types)]
+#[derive(RustcDecodable, Debug)]
+pub enum Kind {
+ dylib,
+ test,
+ bin,
+ lib,
+}
+
+#[derive(RustcDecodable, Debug)]
+pub struct Target {
+ pub name: String,
+ pub kind: Vec<Kind>,
+ src_path: String,
+}
extern crate syntax;
extern crate rustc_plugin;
extern crate clippy_lints;
+extern crate rustc_serialize;
use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session};
use std::path::PathBuf;
use std::process::Command;
+mod cargo;
+
struct ClippyCompilerCalls(RustcDefaultCalls);
impl std::default::Default for ClippyCompilerCalls {
};
if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
- let args = wrap_args(std::env::args().skip(2), dep_path, sys_root);
- let path = std::env::current_exe().expect("current executable path invalid");
- let exit_status = std::process::Command::new("cargo")
- .args(&args)
- .env("RUSTC", path)
- .spawn().expect("could not run cargo")
- .wait().expect("failed to wait for cargo?");
-
- if let Some(code) = exit_status.code() {
- std::process::exit(code);
+ let output = std::process::Command::new("cargo").args(&["metadata", "--no-deps"]).output().expect("could not run `cargo metadata`");
+ let stdout = std::str::from_utf8(&output.stdout).expect("`cargo metadata` output is not utf8");
+ let mut metadata: cargo::Metadata = rustc_serialize::json::decode(stdout).expect("`cargo metadata` output is not valid json");
+ assert_eq!(metadata.version, 1);
+ for target in metadata.packages.remove(0).targets {
+ let args = std::env::args().skip(2);
+ assert_eq!(target.kind.len(), 1);
+ match target.kind[0] {
+ cargo::Kind::dylib => process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root),
+ cargo::Kind::bin => process(vec!["--bin".to_owned(), target.name].into_iter().chain(args), &dep_path, &sys_root),
+ // don't process tests
+ _ => {},
+ }
}
} else {
let args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
}
}
-fn wrap_args<P, I>(old_args: I, dep_path: P, sysroot: String) -> Vec<String>
+fn process<P, I>(old_args: I, dep_path: P, sysroot: &str)
where P: AsRef<Path>, I: Iterator<Item=String> {
let mut args = vec!["rustc".to_owned()];
args.push("-L".to_owned());
args.push(dep_path.as_ref().to_string_lossy().into_owned());
args.push(String::from("--sysroot"));
- args.push(sysroot);
+ args.push(sysroot.to_owned());
args.push("-Zno-trans".to_owned());
- args
+
+ let path = std::env::current_exe().expect("current executable path invalid");
+ let exit_status = std::process::Command::new("cargo")
+ .args(&args)
+ .env("RUSTC", path)
+ .spawn().expect("could not run cargo")
+ .wait().expect("failed to wait for cargo?");
+
+ if let Some(code) = exit_status.code() {
+ std::process::exit(code);
+ }
}