mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:54:42 +00:00
[ty] Make auto-import completions opt-in via an experimental option
Instead of waiting to land auto-import until it is "ready for users," it'd be nicer to get incremental progress merged to `main`. By making it an experimental opt-in, we avoid making the default completion experience worse but permit developers and motivated users to try it.
This commit is contained in:
parent
8e52027a88
commit
0a0eaf5a9b
7 changed files with 63 additions and 16 deletions
|
@ -12,7 +12,17 @@ use crate::find_node::covering_node;
|
|||
use crate::goto::DefinitionsOrTargets;
|
||||
use crate::{Db, all_symbols};
|
||||
|
||||
pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<DetailedCompletion<'_>> {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CompletionSettings {
|
||||
pub auto_import: bool,
|
||||
}
|
||||
|
||||
pub fn completion<'db>(
|
||||
db: &'db dyn Db,
|
||||
settings: &CompletionSettings,
|
||||
file: File,
|
||||
offset: TextSize,
|
||||
) -> Vec<DetailedCompletion<'db>> {
|
||||
let parsed = parsed_module(db, file).load(db);
|
||||
|
||||
let Some(target_token) = CompletionTargetTokens::find(&parsed, offset) else {
|
||||
|
@ -39,6 +49,7 @@ pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<DetailedComp
|
|||
}
|
||||
CompletionTargetAst::Scoped { node } => {
|
||||
let mut completions = model.scoped_completions(node);
|
||||
if settings.auto_import {
|
||||
for symbol in all_symbols(db, "") {
|
||||
completions.push(Completion {
|
||||
name: ast::name::Name::new(&symbol.symbol.name),
|
||||
|
@ -47,6 +58,7 @@ pub fn completion(db: &dyn Db, file: File, offset: TextSize) -> Vec<DetailedComp
|
|||
builtin: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
completions
|
||||
}
|
||||
};
|
||||
|
@ -518,7 +530,7 @@ mod tests {
|
|||
use crate::completion::{DetailedCompletion, completion};
|
||||
use crate::tests::{CursorTest, cursor_test};
|
||||
|
||||
use super::token_suffix_by_kinds;
|
||||
use super::{CompletionSettings, token_suffix_by_kinds};
|
||||
|
||||
#[test]
|
||||
fn token_suffixes_match() {
|
||||
|
@ -3073,7 +3085,8 @@ from os.<CURSOR>
|
|||
predicate: impl Fn(&DetailedCompletion) -> bool,
|
||||
snapshot: impl Fn(&DetailedCompletion) -> String,
|
||||
) -> String {
|
||||
let completions = completion(&self.db, self.cursor.file, self.cursor.offset);
|
||||
let settings = CompletionSettings::default();
|
||||
let completions = completion(&self.db, &settings, self.cursor.file, self.cursor.offset);
|
||||
if completions.is_empty() {
|
||||
return "<No completions found>".to_string();
|
||||
}
|
||||
|
@ -3096,7 +3109,8 @@ from os.<CURSOR>
|
|||
|
||||
#[track_caller]
|
||||
fn assert_completions_include(&self, expected: &str) {
|
||||
let completions = completion(&self.db, self.cursor.file, self.cursor.offset);
|
||||
let settings = CompletionSettings::default();
|
||||
let completions = completion(&self.db, &settings, self.cursor.file, self.cursor.offset);
|
||||
|
||||
assert!(
|
||||
completions
|
||||
|
@ -3108,7 +3122,8 @@ from os.<CURSOR>
|
|||
|
||||
#[track_caller]
|
||||
fn assert_completions_do_not_include(&self, unexpected: &str) {
|
||||
let completions = completion(&self.db, self.cursor.file, self.cursor.offset);
|
||||
let settings = CompletionSettings::default();
|
||||
let completions = completion(&self.db, &settings, self.cursor.file, self.cursor.offset);
|
||||
|
||||
assert!(
|
||||
completions
|
||||
|
|
|
@ -26,7 +26,7 @@ mod symbols;
|
|||
mod workspace_symbols;
|
||||
|
||||
pub use all_symbols::{AllSymbolInfo, all_symbols};
|
||||
pub use completion::completion;
|
||||
pub use completion::{CompletionSettings, completion};
|
||||
pub use doc_highlights::document_highlights;
|
||||
pub use document_symbols::document_symbols;
|
||||
pub use goto::{goto_declaration, goto_definition, goto_type_definition};
|
||||
|
|
|
@ -7,7 +7,7 @@ use lsp_types::{
|
|||
};
|
||||
use ruff_db::source::{line_index, source_text};
|
||||
use ruff_source_file::OneIndexed;
|
||||
use ty_ide::completion;
|
||||
use ty_ide::{CompletionSettings, completion};
|
||||
use ty_project::ProjectDatabase;
|
||||
use ty_python_semantic::CompletionKind;
|
||||
|
||||
|
@ -55,7 +55,10 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler {
|
|||
&line_index,
|
||||
snapshot.encoding(),
|
||||
);
|
||||
let completions = completion(db, file, offset);
|
||||
let settings = CompletionSettings {
|
||||
auto_import: snapshot.global_settings().is_auto_import_enabled(),
|
||||
};
|
||||
let completions = completion(db, &settings, file, offset);
|
||||
if completions.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
|
@ -826,6 +826,7 @@ impl Session {
|
|||
.map_err(DocumentQueryError::InvalidUrl);
|
||||
DocumentSnapshot {
|
||||
resolved_client_capabilities: self.resolved_client_capabilities,
|
||||
global_settings: self.global_settings.clone(),
|
||||
workspace_settings: key
|
||||
.as_ref()
|
||||
.ok()
|
||||
|
@ -1000,6 +1001,7 @@ impl Drop for MutIndexGuard<'_> {
|
|||
#[derive(Debug)]
|
||||
pub(crate) struct DocumentSnapshot {
|
||||
resolved_client_capabilities: ResolvedClientCapabilities,
|
||||
global_settings: Arc<GlobalSettings>,
|
||||
workspace_settings: Arc<WorkspaceSettings>,
|
||||
position_encoding: PositionEncoding,
|
||||
document_query_result: Result<DocumentQuery, DocumentQueryError>,
|
||||
|
@ -1016,6 +1018,11 @@ impl DocumentSnapshot {
|
|||
self.position_encoding
|
||||
}
|
||||
|
||||
/// Returns the client settings for all workspaces.
|
||||
pub(crate) fn global_settings(&self) -> &GlobalSettings {
|
||||
&self.global_settings
|
||||
}
|
||||
|
||||
/// Returns the client settings for the workspace that this document belongs to.
|
||||
pub(crate) fn workspace_settings(&self) -> &WorkspaceSettings {
|
||||
&self.workspace_settings
|
||||
|
|
|
@ -122,6 +122,12 @@ impl ClientOptions {
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_experimental_auto_import(mut self, enabled: bool) -> Self {
|
||||
self.global.experimental.get_or_insert_default().auto_import = Some(enabled);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_unknown(mut self, unknown: HashMap<String, Value>) -> Self {
|
||||
self.unknown = unknown;
|
||||
|
@ -149,6 +155,7 @@ impl GlobalOptions {
|
|||
.experimental
|
||||
.map(|experimental| ExperimentalSettings {
|
||||
rename: experimental.rename.unwrap_or(true),
|
||||
auto_import: experimental.auto_import.unwrap_or(false),
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
|
@ -293,6 +300,12 @@ impl Combine for DiagnosticMode {
|
|||
pub(crate) struct Experimental {
|
||||
/// Whether to enable the experimental symbol rename feature.
|
||||
pub(crate) rename: Option<bool>,
|
||||
/// Whether to enable the experimental "auto-import" feature.
|
||||
///
|
||||
/// At time of writing (2025-08-29), this feature is still
|
||||
/// under active development. It may not work right or may be
|
||||
/// incomplete.
|
||||
pub(crate) auto_import: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||
|
|
|
@ -14,6 +14,10 @@ impl GlobalSettings {
|
|||
pub(crate) fn is_rename_enabled(&self) -> bool {
|
||||
self.experimental.rename
|
||||
}
|
||||
|
||||
pub(crate) fn is_auto_import_enabled(&self) -> bool {
|
||||
self.experimental.auto_import
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalSettings {
|
||||
|
@ -25,6 +29,7 @@ impl GlobalSettings {
|
|||
#[derive(Clone, Default, Debug, PartialEq)]
|
||||
pub(crate) struct ExperimentalSettings {
|
||||
pub(super) rename: bool,
|
||||
pub(super) auto_import: bool,
|
||||
}
|
||||
|
||||
/// Resolved client settings for a specific workspace.
|
||||
|
|
|
@ -415,7 +415,11 @@ impl Workspace {
|
|||
|
||||
let offset = position.to_text_size(&source, &index, self.position_encoding)?;
|
||||
|
||||
let completions = ty_ide::completion(&self.db, file_id.file, offset);
|
||||
// NOTE: At time of writing, 2025-08-29, auto-import isn't
|
||||
// ready to be enabled by default yet. Once it is, we should
|
||||
// either just enable it or provide a way to configure it.
|
||||
let settings = ty_ide::CompletionSettings { auto_import: false };
|
||||
let completions = ty_ide::completion(&self.db, &settings, file_id.file, offset);
|
||||
|
||||
Ok(completions
|
||||
.into_iter()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue