rustc: Add lint for snake_case functions & methods.
This commit is contained in:
parent
874b56d337
commit
16f15ce391
@ -83,6 +83,7 @@ pub enum Lint {
|
||||
NonCamelCaseTypes,
|
||||
NonUppercaseStatics,
|
||||
NonUppercasePatternStatics,
|
||||
NonSnakeCaseFunctions,
|
||||
UppercaseVariables,
|
||||
UnnecessaryParens,
|
||||
TypeLimits,
|
||||
@ -220,6 +221,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
|
||||
default: Warn
|
||||
}),
|
||||
|
||||
("non_snake_case_functions",
|
||||
LintSpec {
|
||||
lint: NonSnakeCaseFunctions,
|
||||
desc: "methods and functions should have snake case names",
|
||||
default: Warn
|
||||
}),
|
||||
|
||||
("uppercase_variables",
|
||||
LintSpec {
|
||||
lint: UppercaseVariables,
|
||||
@ -1342,6 +1350,30 @@ fn check_item_non_camel_case_types(cx: &Context, it: &ast::Item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_snake_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
|
||||
fn is_snake_case(ident: ast::Ident) -> bool {
|
||||
let ident = token::get_ident(ident);
|
||||
assert!(!ident.get().is_empty());
|
||||
let ident = ident.get().trim_chars('_');
|
||||
|
||||
let mut allow_underscore = true;
|
||||
ident.chars().all(|c| {
|
||||
allow_underscore = match c {
|
||||
c if c.is_lowercase() || c.is_digit() => true,
|
||||
'_' if allow_underscore => false,
|
||||
_ => return false,
|
||||
};
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
if !is_snake_case(ident) {
|
||||
cx.span_lint(NonSnakeCaseFunctions, span,
|
||||
format!("{} `{}` should have a snake case identifier",
|
||||
sort, token::get_ident(ident)).as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_non_uppercase_statics(cx: &Context, it: &ast::Item) {
|
||||
match it.node {
|
||||
// only check static constants
|
||||
@ -1618,7 +1650,27 @@ fn check_missing_doc_item(cx: &Context, it: &ast::Item) {
|
||||
desc);
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum MethodContext {
|
||||
TraitDefaultImpl,
|
||||
TraitImpl,
|
||||
PlainImpl
|
||||
}
|
||||
|
||||
fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
|
||||
// If the method is an impl for a trait, don't doc.
|
||||
if method_context(cx, m) == TraitImpl { return; }
|
||||
|
||||
// Otherwise, doc according to privacy. This will also check
|
||||
// doc for default methods defined on traits.
|
||||
check_missing_doc_attrs(cx,
|
||||
Some(m.id),
|
||||
m.attrs.as_slice(),
|
||||
m.span,
|
||||
"a method");
|
||||
}
|
||||
|
||||
fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
|
||||
let did = ast::DefId {
|
||||
krate: ast::LOCAL_CRATE,
|
||||
node: m.id
|
||||
@ -1628,25 +1680,16 @@ fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
|
||||
None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"),
|
||||
Some(md) => {
|
||||
match md.container {
|
||||
// Always check default methods defined on traits.
|
||||
ty::TraitContainer(..) => {}
|
||||
// For methods defined on impls, it depends on whether
|
||||
// it is an implementation for a trait or is a plain
|
||||
// impl.
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => return, // impl for trait: don't doc
|
||||
None => {} // plain impl: doc according to privacy
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
check_missing_doc_attrs(cx,
|
||||
Some(m.id),
|
||||
m.attrs.as_slice(),
|
||||
m.span,
|
||||
"a method");
|
||||
}
|
||||
|
||||
fn check_missing_doc_ty_method(cx: &Context, tm: &ast::TypeMethod) {
|
||||
@ -1889,26 +1932,36 @@ impl<'a> Visitor<()> for Context<'a> {
|
||||
}
|
||||
|
||||
match *fk {
|
||||
visit::FkMethod(_, _, m) => {
|
||||
visit::FkMethod(ident, _, m) => {
|
||||
self.with_lint_attrs(m.attrs.as_slice(), |cx| {
|
||||
check_missing_doc_method(cx, m);
|
||||
check_attrs_usage(cx, m.attrs.as_slice());
|
||||
|
||||
match method_context(cx, m) {
|
||||
PlainImpl => check_snake_case(cx, "method", ident, span),
|
||||
TraitDefaultImpl => check_snake_case(cx, "trait method", ident, span),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
cx.visit_ids(|v| {
|
||||
v.visit_fn(fk, decl, body, span, id, ());
|
||||
});
|
||||
recurse(cx);
|
||||
})
|
||||
},
|
||||
visit::FkItemFn(ident, _, _, _) => {
|
||||
check_snake_case(self, "function", ident, span);
|
||||
recurse(self);
|
||||
}
|
||||
_ => recurse(self),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn visit_ty_method(&mut self, t: &ast::TypeMethod, _: ()) {
|
||||
self.with_lint_attrs(t.attrs.as_slice(), |cx| {
|
||||
check_missing_doc_ty_method(cx, t);
|
||||
check_attrs_usage(cx, t.attrs.as_slice());
|
||||
check_snake_case(cx, "trait method", t.ident, t.span);
|
||||
|
||||
visit::walk_ty_method(cx, t, ());
|
||||
})
|
||||
|
51
src/test/compile-fail/lint-non-snake-case-functions.rs
Normal file
51
src/test/compile-fail/lint-non-snake-case-functions.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(non_snake_case_functions)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn Foo_Method() {}
|
||||
//~^ ERROR method `Foo_Method` should have a snake case identifier
|
||||
|
||||
// Don't allow two underscores in a row
|
||||
fn foo__method(&self) {}
|
||||
//~^ ERROR method `foo__method` should have a snake case identifier
|
||||
|
||||
pub fn xyZ(&mut self) {}
|
||||
//~^ ERROR method `xyZ` should have a snake case identifier
|
||||
}
|
||||
|
||||
trait X {
|
||||
fn ABC();
|
||||
//~^ ERROR trait method `ABC` should have a snake case identifier
|
||||
|
||||
fn a_b_C(&self) {}
|
||||
//~^ ERROR trait method `a_b_C` should have a snake case identifier
|
||||
|
||||
fn something__else(&mut self);
|
||||
//~^ ERROR trait method `something__else` should have a snake case identifier
|
||||
}
|
||||
|
||||
impl X for Foo {
|
||||
// These errors should be caught at the trait definition not the impl
|
||||
fn ABC() {}
|
||||
fn something__else(&mut self) {}
|
||||
}
|
||||
|
||||
fn Cookie() {}
|
||||
//~^ ERROR function `Cookie` should have a snake case identifier
|
||||
|
||||
pub fn bi_S_Cuit() {}
|
||||
//~^ ERROR function `bi_S_Cuit` should have a snake case identifier
|
||||
|
||||
fn main() { }
|
Loading…
x
Reference in New Issue
Block a user