}
macro_rules! define_Conf {
- ($(($toml_name: tt, $rust_name: ident, $default: expr, $ty: ident),)+) => {
+ ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => {
/// Type used to store lint configuration.
pub struct Conf {
- $(pub $rust_name: $ty,)+
+ $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+
}
impl Default for Conf {
fn default() -> Conf {
Conf {
- $($rust_name: $default,)+
+ $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+
}
}
}
match name.as_str() {
$(
define_Conf!(PAT $toml_name) => {
- if let Some(value) = define_Conf!(CONV $ty, value) {
+ if let Some(value) = define_Conf!(CONV $($ty)+, value) {
self.$rust_name = value;
}
else {
return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name),
- stringify!($ty),
+ stringify!($($ty)+),
value.type_str()));
}
},
// hack to convert tts
(PAT $pat: pat) => { $pat };
(EXPR $e: expr) => { $e };
+ (TY $ty: ty) => { $ty };
// how to read the value?
(CONV i64, $value: expr) => { $value.as_integer() };
(CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() };
(CONV String, $value: expr) => { $value.as_str().map(Into::into) };
- (CONV StringVec, $value: expr) => {{
+ (CONV Vec<String>, $value: expr) => {{
let slice = $value.as_slice();
if let Some(slice) = slice {
None
}
}};
-}
-/// To keep the `define_Conf!` macro simple
-pub type StringVec = Vec<String>;
+ // provide a nicer syntax to declare the default value of `Vec<String>` variables
+ (DEFAULT Vec<String>, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() };
+ (DEFAULT $ty: ty, $e: expr) => { $e };
+}
define_Conf! {
- ("blacklisted-names", blacklisted_names, vec!["foo".to_owned(), "bar".to_owned(), "baz".to_owned()], StringVec),
- ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25, u64),
- ("too-many-arguments-threshold", too_many_arguments_threshold, 6, u64),
- ("type-complexity-threshold", type_complexity_threshold, 250, u64),
+ /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about
+ ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec<String>),
+ /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have
+ ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64),
+ /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have
+ ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64),
+ /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have
+ ("type-complexity-threshold", type_complexity_threshold, 250 => u64),
}
/// Read the `toml` configuration file. The function will ignore “File not found” errors iif
level_re = re.compile(r'''(Forbid|Deny|Warn|Allow)''')
+conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE)
+confvar_re = re.compile(r'''/// Lint: (\w+). (.*).*\n *\("([^"]*)", (?:[^,]*), (.*) => (.*)\),''')
def parse_path(p="src"):
for f in os.listdir(p):
if f.endswith(".rs"):
parse_file(d, os.path.join(p, f))
- return d
+ return (d, parse_conf(p))
-START = 0
-LINT = 1
+
+def parse_conf(p):
+ c = {}
+ with open(p + '/conf.rs') as f:
+ f = f.read()
+
+ m = re.search(conf_re, f)
+ m = m.groups()[0]
+
+ m = re.findall(confvar_re, m)
+
+ for (lint, doc, name, default, ty) in m:
+ c[lint.lower()] = (name, ty, doc, default)
+
+ return c
def parse_file(d, f):
%s"""
+conf_template = """
+**Configuration:** This lint has the following configuration variables:
-def write_wiki_page(d, f):
+* `%s: %s`: %s (defaults to `%s`).
+"""
+
+
+def write_wiki_page(d, c, f):
keys = list(d.keys())
keys.sort()
with open(f, "w") as w:
for k in keys:
w.write(template % (k, d[k][0], "".join(d[k][1])))
+ if k in c:
+ w.write(conf_template % c[k])
+
-def check_wiki_page(d, f):
+def check_wiki_page(d, c, f):
errors = []
with open(f) as w:
for line in w:
def main():
- d = parse_path()
+ (d, c) = parse_path()
if "-c" in sys.argv:
- check_wiki_page(d, "../rust-clippy.wiki/Home.md")
+ check_wiki_page(d, c, "../rust-clippy.wiki/Home.md")
else:
- write_wiki_page(d, "../rust-clippy.wiki/Home.md")
+ write_wiki_page(d, c, "../rust-clippy.wiki/Home.md")
if __name__ == "__main__":
main()