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.rs108
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
+) {}
+"#,
+ )
+ }
}