diff --git a/crates/cairo-lang-diagnostics/src/error_code.rs b/crates/cairo-lang-diagnostics/src/error_code.rs index 28a971068df..8aeb8c564e3 100644 --- a/crates/cairo-lang-diagnostics/src/error_code.rs +++ b/crates/cairo-lang-diagnostics/src/error_code.rs @@ -22,12 +22,16 @@ impl ErrorCode { /// Format this error code in a way that is suitable for display in error message. /// /// ``` - /// # use cairo_lang_diagnostics::{codes, error_code}; - /// assert_eq!(error_code!(codes::UNUSED_VARIABLE).display_bracketed(), "[E0001]"); + /// # use cairo_lang_diagnostics::error_code; + /// assert_eq!(error_code!(E0001).display_bracketed(), "[E0001]"); /// ``` pub fn display_bracketed(self) -> String { format!("[{}]", self) } + + pub fn as_str(&self) -> &str { + self.0 + } } impl fmt::Display for ErrorCode { @@ -39,8 +43,8 @@ impl fmt::Display for ErrorCode { /// Constructs an [`ErrorCode`]. /// /// ``` -/// # use cairo_lang_diagnostics::{codes, error_code, ErrorCode}; -/// let code: ErrorCode = error_code!(codes::UNUSED_VARIABLE); +/// # use cairo_lang_diagnostics::{error_code, ErrorCode}; +/// let code: ErrorCode = error_code!(E0001); /// # assert_eq!(format!("{code}"), "E0001"); /// ``` #[macro_export] @@ -48,7 +52,7 @@ macro_rules! error_code { ($code:expr) => {{ use $crate::ErrorCode; // NOTE: This is a magic trick to trigger the validation in compile time. - const ENSURE_CONST: ErrorCode = ErrorCode::new($code); + const ENSURE_CONST: ErrorCode = ErrorCode::new(stringify!($code)); ENSURE_CONST }}; } @@ -62,16 +66,11 @@ impl OptionErrorCodeExt for Option { /// Format this error code in a way that is suitable for display in error message. /// /// ``` - /// # use cairo_lang_diagnostics::{codes, error_code, OptionErrorCodeExt}; - /// assert_eq!(Some(error_code!(codes::UNUSED_VARIABLE)).display_bracketed(), "[E0001]"); + /// # use cairo_lang_diagnostics::{error_code, OptionErrorCodeExt}; + /// assert_eq!(Some(error_code!(E0001)).display_bracketed(), "[E0001]"); /// assert_eq!(None.display_bracketed(), ""); /// ``` fn display_bracketed(self) -> String { self.map(ErrorCode::display_bracketed).unwrap_or_default() } } - -pub mod codes { - /// Unused variable. - pub const UNUSED_VARIABLE: &str = "E0001"; -} diff --git a/crates/cairo-lang-diagnostics/src/lib.rs b/crates/cairo-lang-diagnostics/src/lib.rs index 645549193e5..1ecfc5ef9b5 100644 --- a/crates/cairo-lang-diagnostics/src/lib.rs +++ b/crates/cairo-lang-diagnostics/src/lib.rs @@ -6,7 +6,7 @@ pub use diagnostics::{ DiagnosticNote, Diagnostics, DiagnosticsBuilder, FormattedDiagnosticEntry, Maybe, Severity, ToMaybe, ToOption, }; -pub use error_code::{codes, ErrorCode, OptionErrorCodeExt}; +pub use error_code::{ErrorCode, OptionErrorCodeExt}; pub use location_marks::get_location_marks; mod diagnostics; diff --git a/crates/cairo-lang-language-server/src/lib.rs b/crates/cairo-lang-language-server/src/lib.rs index dbb40041f5e..779cb3a2fee 100644 --- a/crates/cairo-lang-language-server/src/lib.rs +++ b/crates/cairo-lang-language-server/src/lib.rs @@ -21,7 +21,7 @@ use cairo_lang_defs::ids::{ TraitItemId, TraitLongId, UseLongId, }; use cairo_lang_diagnostics::{ - codes, DiagnosticEntry, DiagnosticLocation, Diagnostics, Severity, ToOption, + error_code, DiagnosticEntry, DiagnosticLocation, Diagnostics, Severity, ToOption, }; use cairo_lang_filesystem::cfg::{Cfg, CfgSet}; use cairo_lang_filesystem::db::{ @@ -936,26 +936,16 @@ impl LanguageServer for Backend { #[tracing::instrument(level = "debug", skip_all, fields(uri = %params.text_document.uri))] async fn code_action(&self, params: CodeActionParams) -> LSPResult> { - eprintln!("Code action"); self.with_db(|db| { let mut actions = Vec::with_capacity(params.context.diagnostics.len()); let file_id = file(db, params.text_document.uri.clone()); let (node, _lookup_items) = get_node_and_lookup_items(db, file_id, params.range.start)?; for diagnostic in params.context.diagnostics.iter() { - let action = if let Some(NumberOrString::String(code)) = &diagnostic.code { - match code.as_str() { - codes::UNUSED_VARIABLE => unused_variable( - db, - &node, - diagnostic.clone(), - params.text_document.uri.clone(), - ), - _ => CodeAction::default(), - } - } else { - CodeAction::default() - }; - actions.push(CodeActionOrCommand::from(action)); + actions.extend( + get_code_actions_for_diagnostic(db, &node, diagnostic.clone(), ¶ms) + .into_iter() + .map(CodeActionOrCommand::from), + ); } Some(actions) }) @@ -963,6 +953,31 @@ impl LanguageServer for Backend { } } +fn get_code_actions_for_diagnostic( + db: &dyn SemanticGroup, + node: &SyntaxNode, + diagnostic: Diagnostic, + params: &CodeActionParams, +) -> Vec { + let Some(code) = &diagnostic.code else { + debug!("diagnostic code is missing"); + return vec![]; + }; + + let NumberOrString::String(code) = code else { + debug!("diagnostic code is not a string: `{code:?}`"); + return vec![]; + }; + + let code = code.as_str(); + + if code == error_code!(E0001).as_str() { + vec![unused_variable(db, node, diagnostic.clone(), params.text_document.uri.clone())] + } else { + vec![] + } +} + /// Create a code action that prefixes an unused variable with an `_`. #[tracing::instrument(level = "trace", skip_all)] fn unused_variable( diff --git a/crates/cairo-lang-semantic/src/diagnostic.rs b/crates/cairo-lang-semantic/src/diagnostic.rs index 33eb9db2c82..b0178164155 100644 --- a/crates/cairo-lang-semantic/src/diagnostic.rs +++ b/crates/cairo-lang-semantic/src/diagnostic.rs @@ -8,7 +8,7 @@ use cairo_lang_defs::ids::{ }; use cairo_lang_defs::plugin::PluginDiagnostic; use cairo_lang_diagnostics::{ - codes, error_code, DiagnosticAdded, DiagnosticEntry, DiagnosticLocation, Diagnostics, + error_code, DiagnosticAdded, DiagnosticEntry, DiagnosticLocation, Diagnostics, DiagnosticsBuilder, ErrorCode, Severity, }; use cairo_lang_filesystem::ids::FileId; @@ -1099,7 +1099,7 @@ pub enum SemanticDiagnosticKind { impl SemanticDiagnosticKind { pub fn error_code(&self) -> Option { Some(match &self { - Self::UnusedVariable => error_code!(codes::UNUSED_VARIABLE), + Self::UnusedVariable => error_code!(E0001), _ => return None, }) }