diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index b3e0eb8a670..67af615bf76 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,4 +1,6 @@ -use crate::utils::{iter_input_pats, snippet, span_lint, type_is_unsafe_function}; +use std::convert::TryFrom; + +use crate::utils::{iter_input_pats, snippet, snippet_opt, span_lint, type_is_unsafe_function}; use matches::matches; use rustc::hir; use rustc::hir::def::Def; @@ -8,7 +10,7 @@ use rustc::ty; use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::abi::Abi; -use syntax::source_map::Span; +use syntax::source_map::{BytePos, Span}; declare_clippy_lint! { /// **What it does:** Checks for functions with too many parameters. @@ -162,6 +164,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { impl<'a, 'tcx> Functions { fn check_arg_number(self, cx: &LateContext<'_, '_>, decl: &hir::FnDecl, span: Span) { + // Remove the function body from the span. We can't use `SourceMap::def_span` because the + // argument list might span multiple lines. + let span = if let Some(snippet) = snippet_opt(cx, span) { + let snippet = snippet.split('{').nth(0).unwrap_or("").trim_end(); + if snippet.is_empty() { + span + } else { + span.with_hi(BytePos(span.lo().0 + u32::try_from(snippet.len()).unwrap())) + } + } else { + span + }; + let args = decl.inputs.len() as u64; if args > self.threshold { span_lint( diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 500576d1dff..f8de18dc624 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -7,6 +7,26 @@ fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} +#[rustfmt::skip] +fn bad_multiline( + one: u32, + two: u32, + three: &str, + four: bool, + five: f32, + six: f32, + seven: bool, + eight: () +) { + let _one = one; + let _two = two; + let _three = three; + let _four = four; + let _five = five; + let _six = six; + let _seven = seven; +} + // don't lint extern fns extern "C" fn extern_fn( _one: u32, diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 150b50d9a7c..10d72fb96b1 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -2,24 +2,36 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:8:1 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` error: this function has too many arguments (8/7) - --> $DIR/functions.rs:25:5 + --> $DIR/functions.rs:11:1 + | +LL | / fn bad_multiline( +LL | | one: u32, +LL | | two: u32, +LL | | three: &str, +... | +LL | | eight: () +LL | | ) { + | |_^ + +error: this function has too many arguments (8/7) + --> $DIR/functions.rs:45:5 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many arguments (8/7) - --> $DIR/functions.rs:34:5 + --> $DIR/functions.rs:54:5 | LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:43:34 + --> $DIR/functions.rs:63:34 | LL | println!("{}", unsafe { *p }); | ^ @@ -27,52 +39,52 @@ LL | println!("{}", unsafe { *p }); = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:44:35 + --> $DIR/functions.rs:64:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:45:33 + --> $DIR/functions.rs:65:33 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:56:30 + --> $DIR/functions.rs:76:30 | LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:57:31 + --> $DIR/functions.rs:77:31 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:58:29 + --> $DIR/functions.rs:78:29 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:67:34 + --> $DIR/functions.rs:87:34 | LL | println!("{}", unsafe { *p }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:68:35 + --> $DIR/functions.rs:88:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function dereferences a raw pointer but is not marked `unsafe` - --> $DIR/functions.rs:69:33 + --> $DIR/functions.rs:89:33 | LL | unsafe { std::ptr::read(p) }; | ^ -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors