mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +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.add_to(acc, ctx.db);
|
||||
|
||||
// Completions that skip `.await`, e.g. `.await.foo()`.
|
||||
let dot_access_kind = match &dot_access.kind {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||
}
|
||||
it @ DotAccessKind::Method { .. } => *it,
|
||||
};
|
||||
let dot_access = DotAccess {
|
||||
receiver: dot_access.receiver.clone(),
|
||||
receiver_ty: Some(hir::TypeInfo { original: future_output.clone(), adjusted: None }),
|
||||
kind: dot_access_kind,
|
||||
ctx: dot_access.ctx,
|
||||
};
|
||||
complete_fields(
|
||||
acc,
|
||||
ctx,
|
||||
&future_output,
|
||||
|acc, field, ty| acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty),
|
||||
|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)
|
||||
});
|
||||
if ctx.config.enable_auto_await {
|
||||
// Completions that skip `.await`, e.g. `.await.foo()`.
|
||||
let dot_access_kind = match &dot_access.kind {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||
}
|
||||
it @ DotAccessKind::Method { .. } => *it,
|
||||
};
|
||||
let dot_access = DotAccess {
|
||||
receiver: dot_access.receiver.clone(),
|
||||
receiver_ty: Some(hir::TypeInfo {
|
||||
original: future_output.clone(),
|
||||
adjusted: None,
|
||||
}),
|
||||
kind: dot_access_kind,
|
||||
ctx: dot_access.ctx,
|
||||
};
|
||||
complete_fields(
|
||||
acc,
|
||||
ctx,
|
||||
&future_output,
|
||||
|acc, field, ty| {
|
||||
acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty)
|
||||
},
|
||||
|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(
|
||||
|
|
@ -82,39 +89,41 @@ pub(crate) fn complete_dot(
|
|||
acc.add_method(ctx, dot_access, func, None, None)
|
||||
});
|
||||
|
||||
// FIXME:
|
||||
// Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
|
||||
// its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
|
||||
// Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
|
||||
let iter = receiver_ty
|
||||
.strip_references()
|
||||
.add_reference(hir::Mutability::Shared)
|
||||
.into_iterator_iter(ctx.db)
|
||||
.map(|ty| (ty, SmolStr::new_static("iter()")));
|
||||
// Does <receiver_ty as IntoIterator>::IntoIter` exist?
|
||||
let into_iter = || {
|
||||
receiver_ty
|
||||
.clone()
|
||||
if ctx.config.enable_auto_iter {
|
||||
// FIXME:
|
||||
// Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
|
||||
// its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
|
||||
// Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
|
||||
let iter = receiver_ty
|
||||
.strip_references()
|
||||
.add_reference(hir::Mutability::Shared)
|
||||
.into_iterator_iter(ctx.db)
|
||||
.map(|ty| (ty, SmolStr::new_static("into_iter()")))
|
||||
};
|
||||
if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
|
||||
// Skip iterators, e.g. complete `.iter().filter_map()`.
|
||||
let dot_access_kind = match &dot_access.kind {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||
}
|
||||
it @ DotAccessKind::Method { .. } => *it,
|
||||
.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)
|
||||
.map(|ty| (ty, SmolStr::new_static("into_iter()")))
|
||||
};
|
||||
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)
|
||||
});
|
||||
if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
|
||||
// Skip iterators, e.g. complete `.iter().filter_map()`.
|
||||
let dot_access_kind = match &dot_access.kind {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
|
||||
DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
|
||||
}
|
||||
it @ DotAccessKind::Method { .. } => *it,
|
||||
};
|
||||
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_imports_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_term_search: bool,
|
||||
pub term_search_fuel: u64,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig {
|
|||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||
exclude_flyimport: vec![],
|
||||
exclude_traits: &[],
|
||||
enable_auto_await: true,
|
||||
enable_auto_iter: true,
|
||||
};
|
||||
|
||||
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.
|
||||
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.
|
||||
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
|
||||
completion_autoimport_enable: bool = true,
|
||||
|
|
@ -1484,6 +1488,8 @@ impl Config {
|
|||
enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
|
||||
&& self.caps.completion_item_edit_resolve(),
|
||||
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(),
|
||||
full_function_signatures: self
|
||||
.completion_fullFunctionSignatures_enable(source_root)
|
||||
|
|
|
|||
|
|
@ -176,6 +176,8 @@ fn integrated_completion_benchmark() {
|
|||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||
exclude_flyimport: vec![],
|
||||
exclude_traits: &[],
|
||||
enable_auto_await: true,
|
||||
enable_auto_iter: true,
|
||||
};
|
||||
let position =
|
||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||
|
|
@ -226,6 +228,8 @@ fn integrated_completion_benchmark() {
|
|||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||
exclude_flyimport: vec![],
|
||||
exclude_traits: &[],
|
||||
enable_auto_await: true,
|
||||
enable_auto_iter: true,
|
||||
};
|
||||
let position =
|
||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||
|
|
@ -274,6 +278,8 @@ fn integrated_completion_benchmark() {
|
|||
fields_to_resolve: CompletionFieldsToResolve::empty(),
|
||||
exclude_flyimport: vec![],
|
||||
exclude_traits: &[],
|
||||
enable_auto_await: true,
|
||||
enable_auto_iter: true,
|
||||
};
|
||||
let position =
|
||||
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue