Skip to content

Commit 977e12a

Browse files
committed
Auto merge of rust-lang#12859 - matklad:dont-color-the-whole-block-red-all-the-time-please, r=Veykril
feat: don't highlight the whole fn on return-type mismatch
2 parents 2be0062 + 5bd8443 commit 977e12a

File tree

3 files changed

+69
-40
lines changed

3 files changed

+69
-40
lines changed

crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs

+24-34
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use ide_db::base_db::{FileRange, SourceDatabase};
21
use syntax::{
3-
algo::find_node_at_range,
42
ast::{self, HasArgList},
53
AstNode, TextRange,
64
};
75

8-
use crate::{Diagnostic, DiagnosticsContext};
6+
use crate::{adjusted_display_range, Diagnostic, DiagnosticsContext};
97

108
// Diagnostic: mismatched-arg-count
119
//
@@ -20,40 +18,32 @@ pub(crate) fn mismatched_arg_count(
2018
}
2119

2220
fn invalid_args_range(ctx: &DiagnosticsContext<'_>, d: &hir::MismatchedArgCount) -> TextRange {
23-
let FileRange { file_id, range } =
24-
ctx.sema.diagnostics_display_range(d.call_expr.clone().map(|it| it.into()));
25-
26-
let source_file = ctx.sema.db.parse(file_id);
27-
let expr = find_node_at_range::<ast::Expr>(&source_file.syntax_node(), range)
28-
.filter(|it| it.syntax().text_range() == range);
29-
let arg_list = match expr {
30-
Some(ast::Expr::CallExpr(call)) => call.arg_list(),
31-
Some(ast::Expr::MethodCallExpr(call)) => call.arg_list(),
32-
_ => None,
33-
};
34-
let arg_list = match arg_list {
35-
Some(it) => it,
36-
None => return range,
37-
};
38-
if d.found < d.expected {
39-
if d.found == 0 {
40-
return arg_list.syntax().text_range();
21+
adjusted_display_range::<ast::Expr>(ctx, d.call_expr.clone().map(|it| it.into()), &|expr| {
22+
let arg_list = match expr {
23+
ast::Expr::CallExpr(call) => call.arg_list()?,
24+
ast::Expr::MethodCallExpr(call) => call.arg_list()?,
25+
_ => return None,
26+
};
27+
if d.found < d.expected {
28+
if d.found == 0 {
29+
return Some(arg_list.syntax().text_range());
30+
}
31+
if let Some(r_paren) = arg_list.r_paren_token() {
32+
return Some(r_paren.text_range());
33+
}
4134
}
42-
if let Some(r_paren) = arg_list.r_paren_token() {
43-
return r_paren.text_range();
35+
if d.expected < d.found {
36+
if d.expected == 0 {
37+
return Some(arg_list.syntax().text_range());
38+
}
39+
let zip = arg_list.args().nth(d.expected).zip(arg_list.r_paren_token());
40+
if let Some((arg, r_paren)) = zip {
41+
return Some(arg.syntax().text_range().cover(r_paren.text_range()));
42+
}
4443
}
45-
}
46-
if d.expected < d.found {
47-
if d.expected == 0 {
48-
return arg_list.syntax().text_range();
49-
}
50-
let zip = arg_list.args().nth(d.expected).zip(arg_list.r_paren_token());
51-
if let Some((arg, r_paren)) = zip {
52-
return arg.syntax().text_range().cover(r_paren.text_range());
53-
}
54-
}
5544

56-
range
45+
None
46+
})
5747
}
5848

5949
#[cfg(test)]

crates/ide-diagnostics/src/handlers/type_mismatch.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
11
use hir::{db::AstDatabase, HirDisplay, Type};
22
use ide_db::{famous_defs::FamousDefs, source_change::SourceChange};
33
use syntax::{
4-
ast::{BlockExpr, ExprStmt},
4+
ast::{self, BlockExpr, ExprStmt},
55
AstNode,
66
};
77
use text_edit::TextEdit;
88

9-
use crate::{fix, Assist, Diagnostic, DiagnosticsContext};
9+
use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticsContext};
1010

1111
// Diagnostic: type-mismatch
1212
//
1313
// This diagnostic is triggered when the type of an expression does not match
1414
// the expected type.
1515
pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic {
16+
let display_range = adjusted_display_range::<ast::BlockExpr>(
17+
ctx,
18+
d.expr.clone().map(|it| it.into()),
19+
&|block| {
20+
let r_curly_range = block.stmt_list()?.r_curly_token()?.text_range();
21+
cov_mark::hit!(type_mismatch_on_block);
22+
Some(r_curly_range)
23+
},
24+
);
25+
1626
let mut diag = Diagnostic::new(
1727
"type-mismatch",
1828
format!(
1929
"expected {}, found {}",
2030
d.expected.display(ctx.sema.db),
2131
d.actual.display(ctx.sema.db)
2232
),
23-
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
33+
display_range,
2434
)
2535
.with_fixes(fixes(ctx, d));
2636
if diag.fixes.is_none() {
@@ -545,4 +555,19 @@ fn test() -> String {
545555
"#,
546556
);
547557
}
558+
559+
#[test]
560+
fn type_mismatch_on_block() {
561+
cov_mark::check!(type_mismatch_on_block);
562+
check_diagnostics(
563+
r#"
564+
fn f() -> i32 {
565+
let x = 1;
566+
let y = 2;
567+
let _ = x + y;
568+
}
569+
//^ error: expected i32, found ()
570+
"#,
571+
);
572+
}
548573
}

crates/ide-diagnostics/src/lib.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ mod handlers {
5555
#[cfg(test)]
5656
mod tests;
5757

58-
use hir::{diagnostics::AnyDiagnostic, Semantics};
58+
use hir::{diagnostics::AnyDiagnostic, InFile, Semantics};
5959
use ide_db::{
6060
assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
61-
base_db::{FileId, SourceDatabase},
61+
base_db::{FileId, FileRange, SourceDatabase},
6262
label::Label,
6363
source_change::SourceChange,
6464
FxHashSet, RootDatabase,
6565
};
66-
use syntax::{ast::AstNode, TextRange};
66+
use syntax::{algo::find_node_at_range, ast::AstNode, SyntaxNodePtr, TextRange};
6767

6868
#[derive(Copy, Clone, Debug, PartialEq)]
6969
pub struct DiagnosticCode(pub &'static str);
@@ -244,3 +244,17 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
244244
trigger_signature_help: false,
245245
}
246246
}
247+
248+
fn adjusted_display_range<N: AstNode>(
249+
ctx: &DiagnosticsContext<'_>,
250+
diag_ptr: InFile<SyntaxNodePtr>,
251+
adj: &dyn Fn(N) -> Option<TextRange>,
252+
) -> TextRange {
253+
let FileRange { file_id, range } = ctx.sema.diagnostics_display_range(diag_ptr);
254+
255+
let source_file = ctx.sema.db.parse(file_id);
256+
find_node_at_range::<N>(&source_file.syntax_node(), range)
257+
.filter(|it| it.syntax().text_range() == range)
258+
.and_then(adj)
259+
.unwrap_or(range)
260+
}

0 commit comments

Comments
 (0)