|
1 | 1 | import driver::session::session;
|
2 | 2 | import middle::ty::ctxt;
|
3 | 3 | import syntax::{ast, visit};
|
4 |
| - |
5 |
| -type crate_ctxt = {tcx: ty::ctxt}; |
| 4 | +import front::attr; |
| 5 | +import std::io; |
| 6 | +import io::writer_util; |
6 | 7 |
|
7 | 8 | enum option {
|
8 | 9 | ctypes,
|
9 | 10 | }
|
10 | 11 |
|
| 12 | +impl opt_ for option { |
| 13 | + fn desc() -> str { |
| 14 | + "lint: " + alt self { |
| 15 | + ctypes { "ctypes usage checking" } |
| 16 | + } |
| 17 | + } |
| 18 | + fn run(tcx: ty::ctxt, crate: @ast::crate, time_pass: bool) { |
| 19 | + let checker = alt self { |
| 20 | + ctypes { |
| 21 | + bind check_ctypes(tcx, crate) |
| 22 | + } |
| 23 | + }; |
| 24 | + time(time_pass, self.desc(), checker); |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +// FIXME: Copied from driver.rs, to work around a bug(#1566) |
| 29 | +fn time(do_it: bool, what: str, thunk: block()) { |
| 30 | + if !do_it{ ret thunk(); } |
| 31 | + let start = std::time::precise_time_s(); |
| 32 | + thunk(); |
| 33 | + let end = std::time::precise_time_s(); |
| 34 | + io::stdout().write_str(#fmt("time: %3.3f s\t%s\n", |
| 35 | + end - start, what)); |
| 36 | +} |
| 37 | + |
| 38 | +// Merge lint options specified by crate attributes and rustc command |
| 39 | +// line. Precedence: cmdline > attribute > default |
| 40 | +fn merge_opts(attrs: [ast::attribute], cmd_opts: [(option, bool)]) -> |
| 41 | + [(option, bool)] { |
| 42 | + fn str_to_option(name: str) -> (option, bool) { |
| 43 | + ret alt name { |
| 44 | + "ctypes" { (ctypes, true) } |
| 45 | + "no_ctypes" { (ctypes, false) } |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + fn meta_to_option(meta: @ast::meta_item) -> (option, bool) { |
| 50 | + ret alt meta.node { |
| 51 | + ast::meta_word(name) { |
| 52 | + str_to_option(name) |
| 53 | + } |
| 54 | + }; |
| 55 | + } |
| 56 | + |
| 57 | + fn default() -> [(option, bool)] { |
| 58 | + [(ctypes, true)] |
| 59 | + } |
| 60 | + |
| 61 | + fn contains(xs: [(option, bool)], x: option) -> bool { |
| 62 | + for (o, _) in xs { |
| 63 | + if o == x { ret true; } |
| 64 | + } |
| 65 | + ret false; |
| 66 | + } |
| 67 | + |
| 68 | + let result = cmd_opts; |
| 69 | + |
| 70 | + let lint_metas = |
| 71 | + attr::attr_metas(attr::find_attrs_by_name(attrs, "lint")); |
| 72 | + |
| 73 | + vec::iter(lint_metas) {|mi| |
| 74 | + alt mi.node { |
| 75 | + ast::meta_list(_, list) { |
| 76 | + vec::iter(list) {|e| |
| 77 | + let (o, v) = meta_to_option(e); |
| 78 | + if !contains(cmd_opts, o) { |
| 79 | + result += [(o, v)]; |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + _ { } |
| 84 | + } |
| 85 | + }; |
| 86 | + |
| 87 | + for (o, v) in default() { |
| 88 | + if !contains(result, o) { |
| 89 | + result += [(o, v)]; |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + ret result; |
| 94 | +} |
| 95 | + |
11 | 96 | fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
|
12 | 97 | fn check_native_fn(tcx: ty::ctxt, decl: ast::fn_decl) {
|
13 | 98 | let tys = vec::map(decl.inputs) {|a| a.ty };
|
@@ -52,6 +137,16 @@ fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
|
52 | 137 | });
|
53 | 138 | visit::visit_crate(*crate, (), visit);
|
54 | 139 | }
|
| 140 | + |
| 141 | +fn check_crate(tcx: ty::ctxt, crate: @ast::crate, |
| 142 | + opts: [(option, bool)], time: bool) { |
| 143 | + let lint_opts = lint::merge_opts(crate.node.attrs, opts); |
| 144 | + for (lopt, switch) in lint_opts { |
| 145 | + if switch == true { |
| 146 | + lopt.run(tcx, crate, time); |
| 147 | + } |
| 148 | + } |
| 149 | +} |
55 | 150 | //
|
56 | 151 | // Local Variables:
|
57 | 152 | // mode: rust
|
|
0 commit comments