cairo
cairo copied to clipboard
Add a Quick Fix to add `use` item for missing traits
Implement the following Quick Fix:
fn main() {
// Error: Unknown method.
// Quick Fix: Import `core::num::traits::OverflowingAdd`
let x = 1_i8.overflowing_<caret>add(2)
}
That, when applied, will transform this code into:
+ use core::num::traits::OverflowingAdd;
fn main() {
let x = 1_i8.overflowing_<caret>add(2)
}
This is how this looks like in Rust Analyzer:
Is there a link to the file?
Is there a link to the file?
I don't understand. Please elaborate.
Let me look critically at the code to see where to implement the changes and run some tests. In case I am succesful, I will create a PR
https://github.com/starkware-libs/cairo/blob/037223273235aa6205a75df310a6c605ee9ea46e/crates/cairo-lang-language-server/src/ide/code_actions/mod.rs
Thank you
To implement the quick fix for Rust Analyzer that suggests importing core::num::traits::OverflowingAdd when encountering an unknown method, you can follow these steps:
Step-by-Step Implementation
-
Identify the Problem:
- The code snippet shows an error where
overflowing_addmethod is unknown. - Quick Fix: Import
core::num::traits::OverflowingAddto resolve the issue.
- The code snippet shows an error where
-
Modify the Code:
- We need to implement a code action that suggests adding the import statement when the method is unresolved.
-
Code Implementation:
- Locate the relevant part of the code where code actions are handled, typically in a module related to code actions (
mod.rsor similar). - Add a condition to check for the unresolved method and provide a suggestion to import
OverflowingAdd.
- Locate the relevant part of the code where code actions are handled, typically in a module related to code actions (
-
Example Implementation: Here's how you can implement the quick fix:
use ide::{Context, Diagnostic, DiagnosticCode, DiagnosticSource, FilePosition}; use syntax::{self, ast, AstNode}; pub(crate) fn code_action(ctx: &Context, fix: &ast::UnresolvedMethodFix) -> Option<Diagnostic> { if fix.name_ref.text() == "overflowing_add" { let root = ctx.sema.parse(ctx.frange.file_id); let use_item_path = syntax::ast::Path::from_text("core::num::traits::OverflowingAdd").unwrap(); let edit = ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id, edit: ide::FileEdit { indels: vec![ ide::Indel { insert: true, indel: ide::SingleFileEdit { file_id: fix.frange.file_id, edit: ide::TextEdit { file_id: fix.frange.file_id,
It seems like you've pasted a large block of code here. To implement the quick fix for Rust Analyzer that suggests importing core::num::traits::OverflowingAdd when encountering an unknown method, you should focus on modifying the appropriate part of your Rust codebase where code actions are handled.
Based on the snippet you've shared, it appears you have a placeholder code snippet that needs actual implementation. Here's a streamlined version of how you might approach implementing this fix:
Implementation Steps:
-
Identify the Problem:
- You want to implement a code action that suggests importing
core::num::traits::OverflowingAddwhen encountering an unknown method likeoverflowing_add.
- You want to implement a code action that suggests importing
-
Modify the Code Action Function:
- Locate the function where code actions are defined. This might be in
mod.rsor a similar file related to code actions.
- Locate the function where code actions are defined. This might be in
-
Add Import Suggestion Logic:
- Implement logic to check if the method
overflowing_addis unresolved (UnresolvedMethodFix). - If
overflowing_addis unresolved, suggest addinguse core::num::traits::OverflowingAdd;.
- Implement logic to check if the method
-
Example Code Action Function:
use ide::{Context, Diagnostic, DiagnosticCode, DiagnosticSource, FilePosition}; use syntax::{self, ast, AstNode}; pub(crate) fn code_action(ctx: &Context, fix: &ast::UnresolvedMethodFix) -> Option<Diagnostic> { if fix.name_ref.text() == "overflowing_add" { // Generate the import statement suggestion let import_text = "use core::num::traits::OverflowingAdd;"; let start_offset = 0; // Adjust this according to your context let end_offset = 0; // Adjust this according to your context // Create the diagnostic to suggest adding the import Some(Diagnostic { file: fix.file(), code: DiagnosticCode::UnresolvedMethod, diagnostic_source: DiagnosticSource::Analyzer, severity: Severity::Suggestion, message: "Unknown method. Quick Fix: Import `core::num::traits::OverflowingAdd`".to_string(), actions: vec![TextEdit { range: (start_offset, end_offset), edit: TextEditAction::Insert(import_text.to_string()), }], }) } else { None // No action needed if method is not `overflowing_add` } } -
Integrate and Test:
- Integrate this function into your existing codebase where code actions are handled.
- Test the behavior by triggering the code action suggestion in your IDE when encountering an unresolved
overflowing_addmethod.
-
Adjust Based on Your Project Structure:
- Modify
start_offsetandend_offsetto ensure the import statement is inserted at the correct position in your file.
- Modify
This implementation assumes familiarity with your project's structure and Rust Analyzer's APIs for handling code actions and diagnostics. Adjust the details as per your specific requirements and project setup. Remember to test thoroughly to ensure the code action works as expected in various scenarios.
This can also be useful: https://github.com/starkware-libs/cairo/blob/037223273235aa6205a75df310a6c605ee9ea46e/crates/cairo-lang-language-server/src/ide/completion/completions.rs#L275C5-L281C6
When a method is chosen from the completion menu and the trait is not yet imported, an import is added, this is where it happens.