mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Add diagnostic for break outside of loop
This commit is contained in:
parent
f8bf94a4b9
commit
d0129c4ddb
4 changed files with 62 additions and 1 deletions
|
@ -131,3 +131,31 @@ impl AstDiagnostic for MissingOkInTailExpr {
|
|||
ast::Expr::cast(node).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BreakOutsideOfLoop {
|
||||
pub file: HirFileId,
|
||||
pub expr: AstPtr<ast::Expr>,
|
||||
}
|
||||
|
||||
impl Diagnostic for BreakOutsideOfLoop {
|
||||
fn message(&self) -> String {
|
||||
"break outside of loop".to_string()
|
||||
}
|
||||
fn source(&self) -> InFile<SyntaxNodePtr> {
|
||||
InFile { file_id: self.file, value: self.expr.clone().into() }
|
||||
}
|
||||
fn as_any(&self) -> &(dyn Any + Send + 'static) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AstDiagnostic for BreakOutsideOfLoop {
|
||||
type AST = ast::Expr;
|
||||
|
||||
fn ast(&self, db: &impl AstDatabase) -> Self::AST {
|
||||
let root = db.parse_or_expand(self.file).unwrap();
|
||||
let node = self.source().value.to_node(&root);
|
||||
ast::Expr::cast(node).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -717,11 +717,15 @@ mod diagnostics {
|
|||
use hir_def::{expr::ExprId, FunctionId};
|
||||
use hir_expand::diagnostics::DiagnosticSink;
|
||||
|
||||
use crate::{db::HirDatabase, diagnostics::NoSuchField};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
diagnostics::{BreakOutsideOfLoop, NoSuchField},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub(super) enum InferenceDiagnostic {
|
||||
NoSuchField { expr: ExprId, field: usize },
|
||||
BreakOutsideOfLoop { expr: ExprId },
|
||||
}
|
||||
|
||||
impl InferenceDiagnostic {
|
||||
|
@ -737,6 +741,13 @@ mod diagnostics {
|
|||
let field = source_map.field_syntax(*expr, *field);
|
||||
sink.push(NoSuchField { file: field.file_id, field: field.value })
|
||||
}
|
||||
InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
|
||||
let (_, source_map) = db.body_with_source_map(owner.into());
|
||||
let ptr = source_map
|
||||
.expr_syntax(*expr)
|
||||
.expect("break outside of loop in synthetic syntax");
|
||||
sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,6 +235,10 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
if let Some(ctxt) = self.breakables.last_mut() {
|
||||
ctxt.may_break = true;
|
||||
} else {
|
||||
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
|
||||
expr: tgt_expr,
|
||||
});
|
||||
}
|
||||
Ty::simple(TypeCtor::Never)
|
||||
}
|
||||
|
|
|
@ -518,3 +518,21 @@ fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
|
|||
|
||||
assert_snapshot!(diagnostics, @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn break_outside_of_loop() {
|
||||
let diagnostics = TestDB::with_files(
|
||||
r"
|
||||
//- /lib.rs
|
||||
fn foo() {
|
||||
break;
|
||||
}
|
||||
",
|
||||
)
|
||||
.diagnostics()
|
||||
.0;
|
||||
|
||||
assert_snapshot!(diagnostics, @r###""break": break outside of loop
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue