mirror of https://github.com/astral-sh/ruff
add qualify code-action
This commit is contained in:
parent
bb464ed924
commit
72ef51b7bc
|
|
@ -38,6 +38,11 @@ pub fn code_actions(
|
|||
{
|
||||
actions.extend(import_quick_fix);
|
||||
}
|
||||
if is_unresolved_reference
|
||||
&& let Some(import_quick_fix) = create_qualify_symbol_quick_fix(db, file, diagnostic_range)
|
||||
{
|
||||
actions.extend(import_quick_fix);
|
||||
}
|
||||
|
||||
// Suggest just suppressing the lint (always a valid option, but never ideal)
|
||||
actions.push(QuickFix {
|
||||
|
|
@ -69,6 +74,26 @@ fn create_import_symbol_quick_fix(
|
|||
)
|
||||
}
|
||||
|
||||
fn create_qualify_symbol_quick_fix(
|
||||
db: &dyn Db,
|
||||
file: File,
|
||||
diagnostic_range: TextRange,
|
||||
) -> Option<impl Iterator<Item = QuickFix>> {
|
||||
let parsed = parsed_module(db, file).load(db);
|
||||
let node = covering_node(parsed.syntax().into(), diagnostic_range).node();
|
||||
let symbol = &node.expr_name()?.id;
|
||||
|
||||
Some(
|
||||
completion::missing_qualifications(db, file, &parsed, symbol, node)
|
||||
.into_iter()
|
||||
.map(|import| QuickFix {
|
||||
title: import.label,
|
||||
edits: vec![import.edit],
|
||||
preferred: true,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,29 @@ impl<'db> Completions<'db> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn into_qualified(mut self, range: TextRange) -> Vec<ImportEdit> {
|
||||
self.items.sort_by(compare_suggestions);
|
||||
self.items
|
||||
.dedup_by(|c1, c2| (&c1.name, c1.module_name) == (&c2.name, c2.module_name));
|
||||
self.items
|
||||
.into_iter()
|
||||
.filter_map(|item| {
|
||||
if item.import.is_none() {
|
||||
Some(ImportEdit {
|
||||
label: format!("qualify {}", item.insert.as_ref()?),
|
||||
edit: Edit::replacement(
|
||||
item.insert?.into_string(),
|
||||
range.start(),
|
||||
range.end(),
|
||||
),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Attempts to adds the given completion to this collection.
|
||||
///
|
||||
/// When added, `true` is returned.
|
||||
|
|
@ -578,6 +601,29 @@ pub(crate) fn missing_imports(
|
|||
completions.into_imports()
|
||||
}
|
||||
|
||||
pub(crate) fn missing_qualifications(
|
||||
db: &dyn Db,
|
||||
file: File,
|
||||
parsed: &ParsedModuleRef,
|
||||
symbol: &str,
|
||||
node: AnyNodeRef,
|
||||
) -> Vec<ImportEdit> {
|
||||
let mut completions = Completions::exactly(db, symbol);
|
||||
let scoped = ScopedTarget { node };
|
||||
add_unimported_completions(
|
||||
db,
|
||||
file,
|
||||
parsed,
|
||||
scoped,
|
||||
|module_name: &ModuleName, symbol: &str| {
|
||||
ImportRequest::import(module_name.as_str(), symbol).force()
|
||||
},
|
||||
&mut completions,
|
||||
);
|
||||
|
||||
completions.into_qualified(node.range())
|
||||
}
|
||||
|
||||
/// Adds completions derived from keywords.
|
||||
///
|
||||
/// This should generally only be used when offering "scoped" completions.
|
||||
|
|
|
|||
Loading…
Reference in New Issue