]> git.lizzy.rs Git - rust.git/blob - src/driver.rs
Fix pedantic filter_map warnings
[rust.git] / src / driver.rs
1 // error-pattern:yummy
2 #![feature(box_syntax)]
3 #![feature(rustc_private)]
4 #![feature(tool_lints)]
5 #![allow(unknown_lints, clippy::missing_docs_in_private_items)]
6
7 use rustc_driver::{self, driver::CompileController, Compilation};
8 use rustc_plugin;
9 use std::path::Path;
10 use std::process::{exit, Command};
11
12 #[allow(clippy::print_stdout)]
13 fn show_version() {
14     println!(env!("CARGO_PKG_VERSION"));
15 }
16
17 pub fn main() {
18     exit(rustc_driver::run(move || {
19         use std::env;
20
21         if std::env::args().any(|a| a == "--version" || a == "-V") {
22             show_version();
23             exit(0);
24         }
25
26         let sys_root = option_env!("SYSROOT")
27             .map(String::from)
28             .or_else(|| std::env::var("SYSROOT").ok())
29             .or_else(|| {
30                 let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
31                 let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
32                 home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
33             })
34             .or_else(|| {
35                 Command::new("rustc")
36                     .arg("--print")
37                     .arg("sysroot")
38                     .output()
39                     .ok()
40                     .and_then(|out| String::from_utf8(out.stdout).ok())
41                     .map(|s| s.trim().to_owned())
42             })
43             .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");
44
45         // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
46         // We're invoking the compiler programmatically, so we ignore this/
47         let mut orig_args: Vec<String> = env::args().collect();
48         if orig_args.len() <= 1 {
49             std::process::exit(1);
50         }
51         if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
52             // we still want to be able to invoke it normally though
53             orig_args.remove(1);
54         }
55         // this conditional check for the --sysroot flag is there so users can call
56         // `clippy_driver` directly
57         // without having to pass --sysroot or anything
58         let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
59             orig_args.clone()
60         } else {
61             orig_args
62                 .clone()
63                 .into_iter()
64                 .chain(Some("--sysroot".to_owned()))
65                 .chain(Some(sys_root))
66                 .collect()
67         };
68
69         // this check ensures that dependencies are built but not linted and the final
70         // crate is
71         // linted but not built
72         let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
73             || orig_args.iter().any(|s| s == "--emit=dep-info,metadata");
74
75         if clippy_enabled {
76             args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
77             if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
78                 args.extend(
79                     extra_args
80                         .split("__CLIPPY_HACKERY__")
81                         .filter_map(|s| if s.is_empty() {
82                             None
83                         } else {
84                             Some(s.to_string())
85                         })
86                 );
87             }
88         }
89
90         let mut controller = CompileController::basic();
91         if clippy_enabled {
92             controller.after_parse.callback = Box::new(move |state| {
93                 let mut registry = rustc_plugin::registry::Registry::new(
94                     state.session,
95                     state
96                         .krate
97                         .as_ref()
98                         .expect(
99                             "at this compilation stage \
100                             the crate must be parsed",
101                         )
102                         .span,
103                 );
104                 registry.args_hidden = Some(Vec::new());
105
106                 let conf = clippy_lints::read_conf(&registry);
107                 clippy_lints::register_plugins(&mut registry, &conf);
108
109                 let rustc_plugin::registry::Registry {
110                     early_lint_passes,
111                     late_lint_passes,
112                     lint_groups,
113                     llvm_passes,
114                     attributes,
115                     ..
116                 } = registry;
117                 let sess = &state.session;
118                 let mut ls = sess.lint_store.borrow_mut();
119                 for pass in early_lint_passes {
120                     ls.register_early_pass(Some(sess), true, pass);
121                 }
122                 for pass in late_lint_passes {
123                     ls.register_late_pass(Some(sess), true, pass);
124                 }
125
126                 for (name, (to, deprecated_name)) in lint_groups {
127                     ls.register_group(Some(sess), true, name, deprecated_name, to);
128                 }
129                 clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
130
131                 sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
132                 sess.plugin_attributes.borrow_mut().extend(attributes);
133             });
134         }
135         controller.compilation_done.stop = Compilation::Stop;
136
137         let args = args;
138         rustc_driver::run_compiler(&args, Box::new(controller), None, None)
139     }) as i32)
140 }