Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs')
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 6238c7e09e..8265e0b1c1 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -1,10 +1,37 @@ +use either::Either; +use hir::InFile; use syntax::{ ast::{self, HasArgList}, - AstNode, TextRange, + AstNode, SyntaxNodePtr, TextRange, }; use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; +// Diagnostic: mismatched-tuple-struct-pat-arg-count +// +// This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. +pub(crate) fn mismatched_tuple_struct_pat_arg_count( + ctx: &DiagnosticsContext<'_>, + d: &hir::MismatchedTupleStructPatArgCount, +) -> Diagnostic { + let s = if d.found == 1 { "" } else { "s" }; + let s2 = if d.expected == 1 { "" } else { "s" }; + let message = format!( + "this pattern has {} field{s}, but the corresponding tuple struct has {} field{s2}", + d.found, d.expected + ); + Diagnostic::new( + DiagnosticCode::RustcHardError("E0023"), + message, + invalid_args_range( + ctx, + d.expr_or_pat.clone().map(|it| it.either(Into::into, Into::into)), + d.expected, + d.found, + ), + ) +} + // Diagnostic: mismatched-arg-count // // This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. @@ -14,31 +41,63 @@ pub(crate) fn mismatched_arg_count( ) -> Diagnostic { let s = if d.expected == 1 { "" } else { "s" }; let message = format!("expected {} argument{s}, found {}", d.expected, d.found); - Diagnostic::new(DiagnosticCode::RustcHardError("E0107"), message, invalid_args_range(ctx, d)) + Diagnostic::new( + DiagnosticCode::RustcHardError("E0107"), + message, + invalid_args_range(ctx, d.call_expr.clone().map(Into::into), d.expected, d.found), + ) } -fn invalid_args_range(ctx: &DiagnosticsContext<'_>, d: &hir::MismatchedArgCount) -> TextRange { - adjusted_display_range::<ast::Expr>(ctx, d.call_expr.clone().map(|it| it.into()), &|expr| { - let arg_list = match expr { - ast::Expr::CallExpr(call) => call.arg_list()?, - ast::Expr::MethodCallExpr(call) => call.arg_list()?, +fn invalid_args_range( + ctx: &DiagnosticsContext<'_>, + source: InFile<SyntaxNodePtr>, + expected: usize, + found: usize, +) -> TextRange { + adjusted_display_range::<Either<ast::Expr, ast::TupleStructPat>>(ctx, source, &|expr| { + let (text_range, r_paren_token, expected_arg) = match expr { + Either::Left(ast::Expr::CallExpr(call)) => { + let arg_list = call.arg_list()?; + ( + arg_list.syntax().text_range(), + arg_list.r_paren_token(), + arg_list.args().nth(expected).map(|it| it.syntax().text_range()), + ) + } + Either::Left(ast::Expr::MethodCallExpr(call)) => { + let arg_list = call.arg_list()?; + ( + arg_list.syntax().text_range(), + arg_list.r_paren_token(), + arg_list.args().nth(expected).map(|it| it.syntax().text_range()), + ) + } + Either::Right(pat) => { + let r_paren = pat.r_paren_token()?; + let l_paren = pat.l_paren_token()?; + ( + l_paren.text_range().cover(r_paren.text_range()), + Some(r_paren), + pat.fields().nth(expected).map(|it| it.syntax().text_range()), + ) + } _ => return None, }; - if d.found < d.expected { - if d.found == 0 { - return Some(arg_list.syntax().text_range()); + if found < expected { + if found == 0 { + return Some(text_range); } - if let Some(r_paren) = arg_list.r_paren_token() { + if let Some(r_paren) = r_paren_token { return Some(r_paren.text_range()); } } - if d.expected < d.found { - if d.expected == 0 { - return Some(arg_list.syntax().text_range()); + if expected < found { + if expected == 0 { + return Some(text_range); } - let zip = arg_list.args().nth(d.expected).zip(arg_list.r_paren_token()); + let zip = expected_arg.zip(r_paren_token); if let Some((arg, r_paren)) = zip { - return Some(arg.syntax().text_range().cover(r_paren.text_range())); + return Some(arg.cover(r_paren.text_range())); } } @@ -331,4 +390,21 @@ fn g() { "#, ) } + + #[test] + fn tuple_struct_pat() { + check_diagnostics( + r#" +struct S(u32, u32); +fn f( + S(a, b, c): S, + // ^^ error: this pattern has 3 fields, but the corresponding tuple struct has 2 fields + S(): S, + // ^^ error: this pattern has 0 fields, but the corresponding tuple struct has 2 fields + S(e, f, .., g, d): S + // ^^^^^^^^^ error: this pattern has 4 fields, but the corresponding tuple struct has 2 fields +) {} +"#, + ) + } } |