10499: feat: be more precise in mismatch arg counts highlighting r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2021-10-09 19:46:47 +00:00 committed by GitHub
commit ce86534e1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,3 +1,10 @@
use ide_db::base_db::{FileRange, SourceDatabase};
use syntax::{
algo::find_node_at_range,
ast::{self, HasArgList},
AstNode,
};
use crate::{Diagnostic, DiagnosticsContext}; use crate::{Diagnostic, DiagnosticsContext};
// Diagnostic: mismatched-arg-count // Diagnostic: mismatched-arg-count
@ -12,10 +19,45 @@ pub(crate) fn mismatched_arg_count(
Diagnostic::new( Diagnostic::new(
"mismatched-arg-count", "mismatched-arg-count",
message, message,
ctx.sema.diagnostics_display_range(d.call_expr.clone().map(|it| it.into())).range, invalid_args_range(ctx, d).unwrap_or_else(|it| it).range,
) )
} }
fn invalid_args_range(
ctx: &DiagnosticsContext<'_>,
d: &hir::MismatchedArgCount,
) -> Result<FileRange, FileRange> {
let full_range = ctx.sema.diagnostics_display_range(d.call_expr.clone().map(|it| it.into()));
let source_file = ctx.sema.db.parse(full_range.file_id);
let expr = find_node_at_range::<ast::Expr>(&source_file.syntax_node(), full_range.range)
.filter(|it| it.syntax().text_range() == full_range.range);
let arg_list = match expr {
Some(ast::Expr::CallExpr(call)) => call.arg_list(),
Some(ast::Expr::MethodCallExpr(call)) => call.arg_list(),
_ => None,
};
let arg_list = match arg_list {
Some(it) => it,
None => return Err(full_range),
};
let arg_list_range =
FileRange { file_id: full_range.file_id, range: arg_list.syntax().text_range() };
if d.found < d.expected {
if d.found == 0 {
return Ok(arg_list_range);
}
if let Some(r_paren) = arg_list.r_paren_token() {
return Ok(FileRange { file_id: full_range.file_id, range: r_paren.text_range() });
}
}
if d.expected < d.found {
return Ok(arg_list_range);
}
Err(full_range)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tests::check_diagnostics; use crate::tests::check_diagnostics;
@ -26,7 +68,7 @@ mod tests {
r#" r#"
fn zero() {} fn zero() {}
fn f() { zero(1); } fn f() { zero(1); }
//^^^^^^^ error: expected 0 arguments, found 1 //^^^ error: expected 0 arguments, found 1
"#, "#,
); );
@ -44,7 +86,7 @@ fn f() { zero(); }
r#" r#"
fn one(arg: u8) {} fn one(arg: u8) {}
fn f() { one(); } fn f() { one(); }
//^^^^^ error: expected 1 argument, found 0 //^^ error: expected 1 argument, found 0
"#, "#,
); );
@ -65,7 +107,7 @@ impl S { fn method(&self) {} }
fn f() { fn f() {
S::method(); S::method();
} //^^^^^^^^^^^ error: expected 1 argument, found 0 } //^^ error: expected 1 argument, found 0
"#, "#,
); );
@ -91,7 +133,7 @@ impl S { fn method(&self, arg: u8) {} }
fn f() { fn f() {
S.method(); S.method();
} //^^^^^^^^^^ error: expected 1 argument, found 0 } //^^ error: expected 1 argument, found 0
"#, "#,
); );
@ -131,7 +173,7 @@ fn f() {
struct Tup(u8, u16); struct Tup(u8, u16);
fn f() { fn f() {
Tup(0); Tup(0);
} //^^^^^^ error: expected 2 arguments, found 1 } //^ error: expected 2 arguments, found 1
"#, "#,
) )
} }
@ -143,7 +185,7 @@ fn f() {
enum En { Variant(u8, u16), } enum En { Variant(u8, u16), }
fn f() { fn f() {
En::Variant(0); En::Variant(0);
} //^^^^^^^^^^^^^^ error: expected 2 arguments, found 1 } //^ error: expected 2 arguments, found 1
"#, "#,
) )
} }
@ -162,9 +204,9 @@ impl Foo {
fn new() { fn new() {
Foo::Bar(0); Foo::Bar(0);
Foo::Bar(0, 1); Foo::Bar(0, 1);
//^^^^^^^^^^^^^^ error: expected 1 argument, found 2 //^^^^^^ error: expected 1 argument, found 2
Foo::Bar(); Foo::Bar();
//^^^^^^^^^^ error: expected 1 argument, found 0 //^^ error: expected 1 argument, found 0
} }
} }
"#, "#,
@ -185,7 +227,7 @@ fn f() {
unsafe { unsafe {
fixed(0); fixed(0);
fixed(0, 1); fixed(0, 1);
//^^^^^^^^^^^ error: expected 1 argument, found 2 //^^^^^^ error: expected 1 argument, found 2
varargs(0); varargs(0);
varargs(0, 1); varargs(0, 1);
varargs2(); varargs2();
@ -204,10 +246,10 @@ fn f() {
fn main() { fn main() {
let f = |()| (); let f = |()| ();
f(); f();
//^^^ error: expected 1 argument, found 0 //^^ error: expected 1 argument, found 0
f(()); f(());
f((), ()); f((), ());
//^^^^^^^^^ error: expected 1 argument, found 2 //^^^^^^^^ error: expected 1 argument, found 2
} }
"#, "#,
) )