mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
Merge pull request #18993 from ChayimFriedman2/iter-config
feat: Provide a config to control auto-insertion of `await` and `iter()`
This commit is contained in:
commit
1329e6be49
7 changed files with 111 additions and 56 deletions
|
|
@ -42,31 +42,38 @@ pub(crate) fn complete_dot(
|
||||||
item.detail("expr.await");
|
item.detail("expr.await");
|
||||||
item.add_to(acc, ctx.db);
|
item.add_to(acc, ctx.db);
|
||||||
|
|
||||||
// Completions that skip `.await`, e.g. `.await.foo()`.
|
if ctx.config.enable_auto_await {
|
||||||
let dot_access_kind = match &dot_access.kind {
|
// Completions that skip `.await`, e.g. `.await.foo()`.
|
||||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
let dot_access_kind = match &dot_access.kind {
|
||||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||||
}
|
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||||
it @ DotAccessKind::Method { .. } => *it,
|
}
|
||||||
};
|
it @ DotAccessKind::Method { .. } => *it,
|
||||||
let dot_access = DotAccess {
|
};
|
||||||
receiver: dot_access.receiver.clone(),
|
let dot_access = DotAccess {
|
||||||
receiver_ty: Some(hir::TypeInfo { original: future_output.clone(), adjusted: None }),
|
receiver: dot_access.receiver.clone(),
|
||||||
kind: dot_access_kind,
|
receiver_ty: Some(hir::TypeInfo {
|
||||||
ctx: dot_access.ctx,
|
original: future_output.clone(),
|
||||||
};
|
adjusted: None,
|
||||||
complete_fields(
|
}),
|
||||||
acc,
|
kind: dot_access_kind,
|
||||||
ctx,
|
ctx: dot_access.ctx,
|
||||||
&future_output,
|
};
|
||||||
|acc, field, ty| acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty),
|
complete_fields(
|
||||||
|acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
|
acc,
|
||||||
is_field_access,
|
ctx,
|
||||||
is_method_access_with_parens,
|
&future_output,
|
||||||
);
|
|acc, field, ty| {
|
||||||
complete_methods(ctx, &future_output, &traits_in_scope, |func| {
|
acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty)
|
||||||
acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
|
},
|
||||||
});
|
|acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
|
||||||
|
is_field_access,
|
||||||
|
is_method_access_with_parens,
|
||||||
|
);
|
||||||
|
complete_methods(ctx, &future_output, &traits_in_scope, |func| {
|
||||||
|
acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
complete_fields(
|
complete_fields(
|
||||||
|
|
@ -82,39 +89,41 @@ pub(crate) fn complete_dot(
|
||||||
acc.add_method(ctx, dot_access, func, None, None)
|
acc.add_method(ctx, dot_access, func, None, None)
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME:
|
if ctx.config.enable_auto_iter {
|
||||||
// Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
|
// FIXME:
|
||||||
// its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
|
// Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
|
||||||
// Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
|
// its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
|
||||||
let iter = receiver_ty
|
// Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
|
||||||
.strip_references()
|
let iter = receiver_ty
|
||||||
.add_reference(hir::Mutability::Shared)
|
.strip_references()
|
||||||
.into_iterator_iter(ctx.db)
|
.add_reference(hir::Mutability::Shared)
|
||||||
.map(|ty| (ty, SmolStr::new_static("iter()")));
|
|
||||||
// Does <receiver_ty as IntoIterator>::IntoIter` exist?
|
|
||||||
let into_iter = || {
|
|
||||||
receiver_ty
|
|
||||||
.clone()
|
|
||||||
.into_iterator_iter(ctx.db)
|
.into_iterator_iter(ctx.db)
|
||||||
.map(|ty| (ty, SmolStr::new_static("into_iter()")))
|
.map(|ty| (ty, SmolStr::new_static("iter()")));
|
||||||
};
|
// Does <receiver_ty as IntoIterator>::IntoIter` exist?
|
||||||
if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
|
let into_iter = || {
|
||||||
// Skip iterators, e.g. complete `.iter().filter_map()`.
|
receiver_ty
|
||||||
let dot_access_kind = match &dot_access.kind {
|
.clone()
|
||||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
.into_iterator_iter(ctx.db)
|
||||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
.map(|ty| (ty, SmolStr::new_static("into_iter()")))
|
||||||
}
|
|
||||||
it @ DotAccessKind::Method { .. } => *it,
|
|
||||||
};
|
};
|
||||||
let dot_access = DotAccess {
|
if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
|
||||||
receiver: dot_access.receiver.clone(),
|
// Skip iterators, e.g. complete `.iter().filter_map()`.
|
||||||
receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
|
let dot_access_kind = match &dot_access.kind {
|
||||||
kind: dot_access_kind,
|
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||||
ctx: dot_access.ctx,
|
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||||
};
|
}
|
||||||
complete_methods(ctx, &iter, &traits_in_scope, |func| {
|
it @ DotAccessKind::Method { .. } => *it,
|
||||||
acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
|
};
|
||||||
});
|
let dot_access = DotAccess {
|
||||||
|
receiver: dot_access.receiver.clone(),
|
||||||
|
receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
|
||||||
|
kind: dot_access_kind,
|
||||||
|
ctx: dot_access.ctx,
|
||||||
|
};
|
||||||
|
complete_methods(ctx, &iter, &traits_in_scope, |func| {
|
||||||
|
acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ pub struct CompletionConfig<'a> {
|
||||||
pub enable_postfix_completions: bool,
|
pub enable_postfix_completions: bool,
|
||||||
pub enable_imports_on_the_fly: bool,
|
pub enable_imports_on_the_fly: bool,
|
||||||
pub enable_self_on_the_fly: bool,
|
pub enable_self_on_the_fly: bool,
|
||||||
|
pub enable_auto_iter: bool,
|
||||||
|
pub enable_auto_await: bool,
|
||||||
pub enable_private_editable: bool,
|
pub enable_private_editable: bool,
|
||||||
pub enable_term_search: bool,
|
pub enable_term_search: bool,
|
||||||
pub term_search_fuel: u64,
|
pub term_search_fuel: u64,
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,8 @@ pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig {
|
||||||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||||
exclude_flyimport: vec![],
|
exclude_flyimport: vec![],
|
||||||
exclude_traits: &[],
|
exclude_traits: &[],
|
||||||
|
enable_auto_await: true,
|
||||||
|
enable_auto_iter: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn completion_list(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
|
pub(crate) fn completion_list(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
|
||||||
|
|
|
||||||
|
|
@ -453,6 +453,10 @@ config_data! {
|
||||||
///
|
///
|
||||||
/// In `match` arms it completes a comma instead.
|
/// In `match` arms it completes a comma instead.
|
||||||
completion_addSemicolonToUnit: bool = true,
|
completion_addSemicolonToUnit: bool = true,
|
||||||
|
/// Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
|
||||||
|
completion_autoAwait_enable: bool = true,
|
||||||
|
/// Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
|
||||||
|
completion_autoIter_enable: bool = true,
|
||||||
/// Toggles the additional completions that automatically add imports when completed.
|
/// Toggles the additional completions that automatically add imports when completed.
|
||||||
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
|
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
|
||||||
completion_autoimport_enable: bool = true,
|
completion_autoimport_enable: bool = true,
|
||||||
|
|
@ -1484,6 +1488,8 @@ impl Config {
|
||||||
enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
|
enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
|
||||||
&& self.caps.completion_item_edit_resolve(),
|
&& self.caps.completion_item_edit_resolve(),
|
||||||
enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
|
enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
|
||||||
|
enable_auto_iter: *self.completion_autoIter_enable(source_root),
|
||||||
|
enable_auto_await: *self.completion_autoAwait_enable(source_root),
|
||||||
enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(),
|
enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(),
|
||||||
full_function_signatures: self
|
full_function_signatures: self
|
||||||
.completion_fullFunctionSignatures_enable(source_root)
|
.completion_fullFunctionSignatures_enable(source_root)
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,8 @@ fn integrated_completion_benchmark() {
|
||||||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||||
exclude_flyimport: vec![],
|
exclude_flyimport: vec![],
|
||||||
exclude_traits: &[],
|
exclude_traits: &[],
|
||||||
|
enable_auto_await: true,
|
||||||
|
enable_auto_iter: true,
|
||||||
};
|
};
|
||||||
let position =
|
let position =
|
||||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||||
|
|
@ -226,6 +228,8 @@ fn integrated_completion_benchmark() {
|
||||||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||||
exclude_flyimport: vec![],
|
exclude_flyimport: vec![],
|
||||||
exclude_traits: &[],
|
exclude_traits: &[],
|
||||||
|
enable_auto_await: true,
|
||||||
|
enable_auto_iter: true,
|
||||||
};
|
};
|
||||||
let position =
|
let position =
|
||||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||||
|
|
@ -274,6 +278,8 @@ fn integrated_completion_benchmark() {
|
||||||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||||
exclude_flyimport: vec![],
|
exclude_flyimport: vec![],
|
||||||
exclude_traits: &[],
|
exclude_traits: &[],
|
||||||
|
enable_auto_await: true,
|
||||||
|
enable_auto_iter: true,
|
||||||
};
|
};
|
||||||
let position =
|
let position =
|
||||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,16 @@ Whether to automatically add a semicolon when completing unit-returning function
|
||||||
|
|
||||||
In `match` arms it completes a comma instead.
|
In `match` arms it completes a comma instead.
|
||||||
--
|
--
|
||||||
|
[[rust-analyzer.completion.autoAwait.enable]]rust-analyzer.completion.autoAwait.enable (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
|
||||||
|
--
|
||||||
|
[[rust-analyzer.completion.autoIter.enable]]rust-analyzer.completion.autoIter.enable (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
|
||||||
|
--
|
||||||
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
|
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -1143,6 +1143,26 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "completion",
|
||||||
|
"properties": {
|
||||||
|
"rust-analyzer.completion.autoAwait.enable": {
|
||||||
|
"markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "completion",
|
||||||
|
"properties": {
|
||||||
|
"rust-analyzer.completion.autoIter.enable": {
|
||||||
|
"markdownDescription": "Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "completion",
|
"title": "completion",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue