cairo_lint_core/lints/
panic.rs1use cairo_lang_defs::diagnostic_utils::StableLocation;
2use cairo_lang_defs::ids::ModuleItemId;
3use cairo_lang_defs::plugin::PluginDiagnostic;
4use cairo_lang_diagnostics::Severity;
5use cairo_lang_filesystem::db::get_originating_location;
6use cairo_lang_semantic::db::SemanticGroup;
7use cairo_lang_semantic::ExprFunctionCall;
8use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode};
9use if_chain::if_chain;
10
11use crate::context::{CairoLintKind, Lint};
12use crate::queries::{get_all_function_bodies, get_all_function_calls};
13
14const PANIC: &str = "core::panics::panic";
15
16pub struct PanicInCode;
17
18impl Lint for PanicInCode {
30 fn allowed_name(&self) -> &'static str {
31 "panic"
32 }
33
34 fn diagnostic_message(&self) -> &'static str {
35 "Leaving `panic` in the code is discouraged."
36 }
37
38 fn kind(&self) -> CairoLintKind {
39 CairoLintKind::Panic
40 }
41}
42
43pub fn check_panic_usage(
45 db: &dyn SemanticGroup,
46 item: &ModuleItemId,
47 diagnostics: &mut Vec<PluginDiagnostic>,
48) {
49 let function_bodies = get_all_function_bodies(db, item);
50 for function_body in function_bodies.iter() {
51 let function_call_exprs = get_all_function_calls(function_body);
52 for function_call_expr in function_call_exprs.iter() {
53 check_single_panic_usage(db, function_call_expr, diagnostics);
54 }
55 }
56}
57
58fn check_single_panic_usage(
59 db: &dyn SemanticGroup,
60 function_call_expr: &ExprFunctionCall,
61 diagnostics: &mut Vec<PluginDiagnostic>,
62) {
63 let init_node = function_call_expr
64 .stable_ptr
65 .lookup(db.upcast())
66 .as_syntax_node()
67 .clone();
68
69 if function_call_expr.function.full_path(db) != PANIC {
71 return;
72 }
73
74 let initial_file_id =
77 StableLocation::new(function_call_expr.stable_ptr.untyped()).file_id(db.upcast());
78 let (file_id, span) = get_originating_location(
79 db.upcast(),
80 initial_file_id,
81 function_call_expr
82 .stable_ptr
83 .lookup(db.upcast())
84 .as_syntax_node()
85 .span(db.upcast()),
86 None,
87 );
88 if initial_file_id == file_id {
90 diagnostics.push(PluginDiagnostic {
91 stable_ptr: init_node.stable_ptr(),
92 message: PanicInCode.diagnostic_message().to_owned(),
93 severity: Severity::Warning,
94 });
95 } else {
96 if_chain! {
99 if let Some(text_position) = span.position_in_file(db.upcast(), file_id);
100 if let Ok(file_node) = db.file_syntax(file_id);
101 then {
102 let syntax_node = file_node.lookup_position(db.upcast(), text_position.start);
103 diagnostics.push(PluginDiagnostic {
104 stable_ptr: syntax_node.stable_ptr(),
105 message: PanicInCode.diagnostic_message().to_owned(),
106 severity: Severity::Warning,
107 });
108 }
109 }
110 }
111}