rustc: Add lint for snake_case functions & methods.
This commit is contained in:
parent
874b56d337
commit
16f15ce391
2 changed files with 118 additions and 14 deletions
|
@ -83,6 +83,7 @@ pub enum Lint {
|
||||||
NonCamelCaseTypes,
|
NonCamelCaseTypes,
|
||||||
NonUppercaseStatics,
|
NonUppercaseStatics,
|
||||||
NonUppercasePatternStatics,
|
NonUppercasePatternStatics,
|
||||||
|
NonSnakeCaseFunctions,
|
||||||
UppercaseVariables,
|
UppercaseVariables,
|
||||||
UnnecessaryParens,
|
UnnecessaryParens,
|
||||||
TypeLimits,
|
TypeLimits,
|
||||||
|
@ -220,6 +221,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
|
||||||
default: Warn
|
default: Warn
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
("non_snake_case_functions",
|
||||||
|
LintSpec {
|
||||||
|
lint: NonSnakeCaseFunctions,
|
||||||
|
desc: "methods and functions should have snake case names",
|
||||||
|
default: Warn
|
||||||
|
}),
|
||||||
|
|
||||||
("uppercase_variables",
|
("uppercase_variables",
|
||||||
LintSpec {
|
LintSpec {
|
||||||
lint: UppercaseVariables,
|
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) {
|
fn check_item_non_uppercase_statics(cx: &Context, it: &ast::Item) {
|
||||||
match it.node {
|
match it.node {
|
||||||
// only check static constants
|
// only check static constants
|
||||||
|
@ -1618,7 +1650,27 @@ fn check_missing_doc_item(cx: &Context, it: &ast::Item) {
|
||||||
desc);
|
desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
enum MethodContext {
|
||||||
|
TraitDefaultImpl,
|
||||||
|
TraitImpl,
|
||||||
|
PlainImpl
|
||||||
|
}
|
||||||
|
|
||||||
fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
|
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 {
|
let did = ast::DefId {
|
||||||
krate: ast::LOCAL_CRATE,
|
krate: ast::LOCAL_CRATE,
|
||||||
node: m.id
|
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?!"),
|
None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"),
|
||||||
Some(md) => {
|
Some(md) => {
|
||||||
match md.container {
|
match md.container {
|
||||||
// Always check default methods defined on traits.
|
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||||
ty::TraitContainer(..) => {}
|
|
||||||
// For methods defined on impls, it depends on whether
|
|
||||||
// it is an implementation for a trait or is a plain
|
|
||||||
// impl.
|
|
||||||
ty::ImplContainer(cid) => {
|
ty::ImplContainer(cid) => {
|
||||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||||
Some(..) => return, // impl for trait: don't doc
|
Some(..) => TraitImpl,
|
||||||
None => {} // plain impl: doc according to privacy
|
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) {
|
fn check_missing_doc_ty_method(cx: &Context, tm: &ast::TypeMethod) {
|
||||||
|
@ -1889,26 +1932,36 @@ impl<'a> Visitor<()> for Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match *fk {
|
match *fk {
|
||||||
visit::FkMethod(_, _, m) => {
|
visit::FkMethod(ident, _, m) => {
|
||||||
self.with_lint_attrs(m.attrs.as_slice(), |cx| {
|
self.with_lint_attrs(m.attrs.as_slice(), |cx| {
|
||||||
check_missing_doc_method(cx, m);
|
check_missing_doc_method(cx, m);
|
||||||
check_attrs_usage(cx, m.attrs.as_slice());
|
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| {
|
cx.visit_ids(|v| {
|
||||||
v.visit_fn(fk, decl, body, span, id, ());
|
v.visit_fn(fk, decl, body, span, id, ());
|
||||||
});
|
});
|
||||||
recurse(cx);
|
recurse(cx);
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
visit::FkItemFn(ident, _, _, _) => {
|
||||||
|
check_snake_case(self, "function", ident, span);
|
||||||
|
recurse(self);
|
||||||
}
|
}
|
||||||
_ => recurse(self),
|
_ => recurse(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn visit_ty_method(&mut self, t: &ast::TypeMethod, _: ()) {
|
fn visit_ty_method(&mut self, t: &ast::TypeMethod, _: ()) {
|
||||||
self.with_lint_attrs(t.attrs.as_slice(), |cx| {
|
self.with_lint_attrs(t.attrs.as_slice(), |cx| {
|
||||||
check_missing_doc_ty_method(cx, t);
|
check_missing_doc_ty_method(cx, t);
|
||||||
check_attrs_usage(cx, t.attrs.as_slice());
|
check_attrs_usage(cx, t.attrs.as_slice());
|
||||||
|
check_snake_case(cx, "trait method", t.ident, t.span);
|
||||||
|
|
||||||
visit::walk_ty_method(cx, t, ());
|
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…
Add table
Add a link
Reference in a new issue