Skip to content

Commit 5bd8443

Browse files
committed
internal: extract common code for adjusting diagnostic range
1 parent a436be4 commit 5bd8443

File tree

3 files changed

+53
-55
lines changed

3 files changed

+53
-55
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

+12-18
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
11
use hir::{db::AstDatabase, HirDisplay, Type};
2-
use ide_db::{
3-
base_db::{FileRange, SourceDatabase},
4-
famous_defs::FamousDefs,
5-
source_change::SourceChange,
6-
};
2+
use ide_db::{famous_defs::FamousDefs, source_change::SourceChange};
73
use syntax::{
8-
algo::find_node_at_range,
94
ast::{self, BlockExpr, ExprStmt},
105
AstNode,
116
};
127
use text_edit::TextEdit;
138

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

1611
// Diagnostic: type-mismatch
1712
//
1813
// This diagnostic is triggered when the type of an expression does not match
1914
// the expected type.
2015
pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic {
21-
let FileRange { file_id, range } =
22-
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into()));
23-
24-
let source_file = ctx.sema.db.parse(file_id);
25-
let block = find_node_at_range::<ast::BlockExpr>(&source_file.syntax_node(), range)
26-
.filter(|it| it.syntax().text_range() == range);
27-
let display_range = block
28-
.and_then(|it| it.stmt_list())
29-
.and_then(|it| it.r_curly_token())
30-
.map(|it| it.text_range())
31-
.unwrap_or(range);
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+
);
3225

3326
let mut diag = Diagnostic::new(
3427
"type-mismatch",
@@ -565,6 +558,7 @@ fn test() -> String {
565558

566559
#[test]
567560
fn type_mismatch_on_block() {
561+
cov_mark::check!(type_mismatch_on_block);
568562
check_diagnostics(
569563
r#"
570564
fn f() -> i32 {

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)