## Summary Originally I planned to feed this in as a `fix` but I realized that we probably don't want to be trying to resolve import suggestions while we're doing type inference. Thus I implemented this as a fallback when there's no fixes on a diagnostic, which can use the full lsp machinery. Fixes https://github.com/astral-sh/ty/issues/1552 ## Test Plan Works in the IDE, added some e2e tests.
44 lines
1.2 KiB
Rust
44 lines
1.2 KiB
Rust
use crate::{completion, find_node::covering_node};
|
|
use ruff_db::{files::File, parsed::parsed_module};
|
|
use ruff_diagnostics::Edit;
|
|
use ruff_text_size::TextRange;
|
|
use ty_project::Db;
|
|
use ty_python_semantic::types::UNRESOLVED_REFERENCE;
|
|
|
|
/// A `QuickFix` Code Action
|
|
#[derive(Debug, Clone)]
|
|
pub struct QuickFix {
|
|
pub title: String,
|
|
pub edits: Vec<Edit>,
|
|
pub preferred: bool,
|
|
}
|
|
|
|
pub fn code_actions(
|
|
db: &dyn Db,
|
|
file: File,
|
|
diagnostic_range: TextRange,
|
|
diagnostic_id: &str,
|
|
) -> Option<Vec<QuickFix>> {
|
|
let registry = db.lint_registry();
|
|
let Ok(lint_id) = registry.get(diagnostic_id) else {
|
|
return None;
|
|
};
|
|
if lint_id.name() == UNRESOLVED_REFERENCE.name() {
|
|
let parsed = parsed_module(db, file).load(db);
|
|
let node = covering_node(parsed.syntax().into(), diagnostic_range).node();
|
|
let symbol = &node.expr_name()?.id;
|
|
|
|
let fixes = completion::missing_imports(db, file, &parsed, symbol, node)
|
|
.into_iter()
|
|
.map(|import| QuickFix {
|
|
title: import.label,
|
|
edits: vec![import.edit],
|
|
preferred: true,
|
|
})
|
|
.collect();
|
|
Some(fixes)
|
|
} else {
|
|
None
|
|
}
|
|
}
|