mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #19704 from Veykril/push-wrvznvvpvtvp
Add expression fill mode variant for filling with underscore expressions
This commit is contained in:
commit
0fee71065b
@ -86,7 +86,7 @@ impl ModDir {
|
|||||||
let dir_path = if root_dir_owner {
|
let dir_path = if root_dir_owner {
|
||||||
DirPath::empty()
|
DirPath::empty()
|
||||||
} else {
|
} else {
|
||||||
DirPath::new(format!("{}/", name))
|
DirPath::new(format!("{name}/"))
|
||||||
};
|
};
|
||||||
if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
|
if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
|
||||||
return Ok((
|
return Ok((
|
||||||
|
@ -752,8 +752,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
|
|||||||
err: Some(ExpandError::other(
|
err: Some(ExpandError::other(
|
||||||
tt.delimiter.open,
|
tt.delimiter.open,
|
||||||
format!(
|
format!(
|
||||||
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
|
"macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}",
|
||||||
count, TOKEN_LIMIT,
|
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
|
@ -206,8 +206,7 @@ impl ExpandErrorKind {
|
|||||||
},
|
},
|
||||||
None => RenderedExpandError {
|
None => RenderedExpandError {
|
||||||
message: format!(
|
message: format!(
|
||||||
"internal error: proc-macro map is missing error entry for crate {:?}",
|
"internal error: proc-macro map is missing error entry for crate {def_crate:?}"
|
||||||
def_crate
|
|
||||||
),
|
),
|
||||||
error: true,
|
error: true,
|
||||||
kind: RenderedExpandError::GENERAL_KIND,
|
kind: RenderedExpandError::GENERAL_KIND,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
//! assists if we are allowed to.
|
//! assists if we are allowed to.
|
||||||
|
|
||||||
use hir::ImportPathConfig;
|
use hir::ImportPathConfig;
|
||||||
use ide_db::{SnippetCap, imports::insert_use::InsertUseConfig};
|
use ide_db::{SnippetCap, assists::ExprFillDefaultMode, imports::insert_use::InsertUseConfig};
|
||||||
|
|
||||||
use crate::AssistKind;
|
use crate::AssistKind;
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ pub struct AssistConfig {
|
|||||||
pub term_search_fuel: u64,
|
pub term_search_fuel: u64,
|
||||||
pub term_search_borrowck: bool,
|
pub term_search_borrowck: bool,
|
||||||
pub code_action_grouping: bool,
|
pub code_action_grouping: bool,
|
||||||
|
pub expr_fill_default: ExprFillDefaultMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssistConfig {
|
impl AssistConfig {
|
||||||
|
@ -150,6 +150,7 @@ fn add_missing_impl_members_inner(
|
|||||||
let new_impl_def = edit.make_mut(impl_def.clone());
|
let new_impl_def = edit.make_mut(impl_def.clone());
|
||||||
let first_new_item = add_trait_assoc_items_to_impl(
|
let first_new_item = add_trait_assoc_items_to_impl(
|
||||||
&ctx.sema,
|
&ctx.sema,
|
||||||
|
ctx.config,
|
||||||
&missing_items,
|
&missing_items,
|
||||||
trait_,
|
trait_,
|
||||||
&new_impl_def,
|
&new_impl_def,
|
||||||
|
@ -3,6 +3,7 @@ use std::iter::{self, Peekable};
|
|||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym};
|
use hir::{Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym};
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
|
use ide_db::assists::ExprFillDefaultMode;
|
||||||
use ide_db::syntax_helpers::suggest_name;
|
use ide_db::syntax_helpers::suggest_name;
|
||||||
use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
|
use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -216,7 +217,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
|
|||||||
// filter out hidden patterns because they're handled by the catch-all arm
|
// filter out hidden patterns because they're handled by the catch-all arm
|
||||||
!hidden
|
!hidden
|
||||||
})
|
})
|
||||||
.map(|(pat, _)| make.match_arm(pat, None, make::ext::expr_todo()));
|
.map(|(pat, _)| {
|
||||||
|
make.match_arm(
|
||||||
|
pat,
|
||||||
|
None,
|
||||||
|
match ctx.config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let mut arms: Vec<_> = match_arm_list
|
let mut arms: Vec<_> = match_arm_list
|
||||||
.arms()
|
.arms()
|
||||||
@ -246,7 +257,15 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
|
|||||||
|
|
||||||
if needs_catch_all_arm && !has_catch_all_arm {
|
if needs_catch_all_arm && !has_catch_all_arm {
|
||||||
cov_mark::hit!(added_wildcard_pattern);
|
cov_mark::hit!(added_wildcard_pattern);
|
||||||
let arm = make.match_arm(make.wildcard_pat().into(), None, make::ext::expr_todo());
|
let arm = make.match_arm(
|
||||||
|
make.wildcard_pat().into(),
|
||||||
|
None,
|
||||||
|
match ctx.config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
},
|
||||||
|
);
|
||||||
arms.push(arm);
|
arms.push(arm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleDat
|
|||||||
.map(|(id, ty)| {
|
.map(|(id, ty)| {
|
||||||
match name_generator.for_type(&ty, ctx.db(), ctx.edition()) {
|
match name_generator.for_type(&ty, ctx.db(), ctx.edition()) {
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => name_generator.suggest_name(&format!("_{}", id)),
|
None => name_generator.suggest_name(&format!("_{id}")),
|
||||||
}
|
}
|
||||||
.to_string()
|
.to_string()
|
||||||
})
|
})
|
||||||
|
@ -4,6 +4,7 @@ use hir::{
|
|||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap,
|
FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap,
|
||||||
|
assists::ExprFillDefaultMode,
|
||||||
defs::{Definition, NameRefClass},
|
defs::{Definition, NameRefClass},
|
||||||
famous_defs::FamousDefs,
|
famous_defs::FamousDefs,
|
||||||
helpers::is_editable_crate,
|
helpers::is_editable_crate,
|
||||||
@ -276,7 +277,11 @@ impl FunctionBuilder {
|
|||||||
target_module,
|
target_module,
|
||||||
&mut necessary_generic_params,
|
&mut necessary_generic_params,
|
||||||
);
|
);
|
||||||
let placeholder_expr = make::ext::expr_todo();
|
let placeholder_expr = match ctx.config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
};
|
||||||
fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -331,7 +336,11 @@ impl FunctionBuilder {
|
|||||||
let (generic_param_list, where_clause) =
|
let (generic_param_list, where_clause) =
|
||||||
fn_generic_params(ctx, necessary_generic_params, &target)?;
|
fn_generic_params(ctx, necessary_generic_params, &target)?;
|
||||||
|
|
||||||
let placeholder_expr = make::ext::expr_todo();
|
let placeholder_expr = match ctx.config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
};
|
||||||
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
@ -444,7 +453,11 @@ fn make_fn_body_as_new_function(
|
|||||||
let adt_info = adt_info.as_ref()?;
|
let adt_info = adt_info.as_ref()?;
|
||||||
|
|
||||||
let path_self = make::ext::ident_path("Self");
|
let path_self = make::ext::ident_path("Self");
|
||||||
let placeholder_expr = make::ext::expr_todo();
|
let placeholder_expr = match ctx.config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
};
|
||||||
let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() {
|
let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() {
|
||||||
match strukt.kind(ctx.db()) {
|
match strukt.kind(ctx.db()) {
|
||||||
StructKind::Record => {
|
StructKind::Record => {
|
||||||
|
@ -9,7 +9,7 @@ use syntax::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AssistId,
|
AssistConfig, AssistId,
|
||||||
assist_context::{AssistContext, Assists, SourceChangeBuilder},
|
assist_context::{AssistContext, Assists, SourceChangeBuilder},
|
||||||
utils::{
|
utils::{
|
||||||
DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
|
DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
|
||||||
@ -128,8 +128,14 @@ fn add_assist(
|
|||||||
acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
|
acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
|
||||||
let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax());
|
let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax());
|
||||||
let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
|
let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
|
||||||
let impl_def_with_items =
|
let impl_def_with_items = impl_def_from_trait(
|
||||||
impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path);
|
&ctx.sema,
|
||||||
|
ctx.config,
|
||||||
|
adt,
|
||||||
|
&annotated_name,
|
||||||
|
trait_,
|
||||||
|
replace_trait_path,
|
||||||
|
);
|
||||||
update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
|
update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
|
||||||
|
|
||||||
let trait_path = make::ty_path(replace_trait_path.clone());
|
let trait_path = make::ty_path(replace_trait_path.clone());
|
||||||
@ -217,6 +223,7 @@ fn add_assist(
|
|||||||
|
|
||||||
fn impl_def_from_trait(
|
fn impl_def_from_trait(
|
||||||
sema: &hir::Semantics<'_, ide_db::RootDatabase>,
|
sema: &hir::Semantics<'_, ide_db::RootDatabase>,
|
||||||
|
config: &AssistConfig,
|
||||||
adt: &ast::Adt,
|
adt: &ast::Adt,
|
||||||
annotated_name: &ast::Name,
|
annotated_name: &ast::Name,
|
||||||
trait_: Option<hir::Trait>,
|
trait_: Option<hir::Trait>,
|
||||||
@ -241,7 +248,7 @@ fn impl_def_from_trait(
|
|||||||
let impl_def = generate_trait_impl(adt, make::ty_path(trait_path.clone()));
|
let impl_def = generate_trait_impl(adt, make::ty_path(trait_path.clone()));
|
||||||
|
|
||||||
let first_assoc_item =
|
let first_assoc_item =
|
||||||
add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope);
|
add_trait_assoc_items_to_impl(sema, config, &trait_items, trait_, &impl_def, &target_scope);
|
||||||
|
|
||||||
// Generate a default `impl` function body for the derived trait.
|
// Generate a default `impl` function body for the derived trait.
|
||||||
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
|
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
|
||||||
|
@ -4,6 +4,7 @@ use expect_test::expect;
|
|||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
EditionedFileId, FileRange, RootDatabase, SnippetCap,
|
EditionedFileId, FileRange, RootDatabase, SnippetCap,
|
||||||
|
assists::ExprFillDefaultMode,
|
||||||
base_db::SourceDatabase,
|
base_db::SourceDatabase,
|
||||||
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
||||||
source_change::FileSystemEdit,
|
source_change::FileSystemEdit,
|
||||||
@ -35,6 +36,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
|
|||||||
term_search_fuel: 400,
|
term_search_fuel: 400,
|
||||||
term_search_borrowck: true,
|
term_search_borrowck: true,
|
||||||
code_action_grouping: true,
|
code_action_grouping: true,
|
||||||
|
expr_fill_default: ExprFillDefaultMode::Todo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig {
|
pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig {
|
||||||
@ -54,6 +56,7 @@ pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig {
|
|||||||
term_search_fuel: 400,
|
term_search_fuel: 400,
|
||||||
term_search_borrowck: true,
|
term_search_borrowck: true,
|
||||||
code_action_grouping: false,
|
code_action_grouping: false,
|
||||||
|
expr_fill_default: ExprFillDefaultMode::Todo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
|
pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
|
||||||
@ -73,6 +76,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
|
|||||||
term_search_fuel: 400,
|
term_search_fuel: 400,
|
||||||
term_search_borrowck: true,
|
term_search_borrowck: true,
|
||||||
code_action_grouping: true,
|
code_action_grouping: true,
|
||||||
|
expr_fill_default: ExprFillDefaultMode::Todo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
|
pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
|
||||||
@ -92,6 +96,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
|
|||||||
term_search_fuel: 400,
|
term_search_fuel: 400,
|
||||||
term_search_borrowck: true,
|
term_search_borrowck: true,
|
||||||
code_action_grouping: true,
|
code_action_grouping: true,
|
||||||
|
expr_fill_default: ExprFillDefaultMode::Todo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) {
|
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) {
|
||||||
|
@ -8,6 +8,7 @@ use hir::{
|
|||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
|
assists::ExprFillDefaultMode,
|
||||||
famous_defs::FamousDefs,
|
famous_defs::FamousDefs,
|
||||||
path_transform::PathTransform,
|
path_transform::PathTransform,
|
||||||
syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion},
|
syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion},
|
||||||
@ -27,7 +28,10 @@ use syntax::{
|
|||||||
ted,
|
ted,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::assist_context::{AssistContext, SourceChangeBuilder};
|
use crate::{
|
||||||
|
AssistConfig,
|
||||||
|
assist_context::{AssistContext, SourceChangeBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
mod gen_trait_fn_body;
|
mod gen_trait_fn_body;
|
||||||
pub(crate) mod ref_field_expr;
|
pub(crate) mod ref_field_expr;
|
||||||
@ -174,6 +178,7 @@ pub fn filter_assoc_items(
|
|||||||
/// inserted.
|
/// inserted.
|
||||||
pub fn add_trait_assoc_items_to_impl(
|
pub fn add_trait_assoc_items_to_impl(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
|
config: &AssistConfig,
|
||||||
original_items: &[InFile<ast::AssocItem>],
|
original_items: &[InFile<ast::AssocItem>],
|
||||||
trait_: hir::Trait,
|
trait_: hir::Trait,
|
||||||
impl_: &ast::Impl,
|
impl_: &ast::Impl,
|
||||||
@ -219,7 +224,14 @@ pub fn add_trait_assoc_items_to_impl(
|
|||||||
match &item {
|
match &item {
|
||||||
ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
|
ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
|
||||||
let body = AstNodeEdit::indent(
|
let body = AstNodeEdit::indent(
|
||||||
&make::block_expr(None, Some(make::ext::expr_todo())),
|
&make::block_expr(
|
||||||
|
None,
|
||||||
|
Some(match config.expr_fill_default {
|
||||||
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => make::ext::expr_todo(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
new_indent_level,
|
new_indent_level,
|
||||||
);
|
);
|
||||||
ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
|
ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
|
||||||
|
@ -135,7 +135,7 @@ impl fmt::Debug for CompletionItem {
|
|||||||
},
|
},
|
||||||
CompletionItemRefMode::Dereference => "*",
|
CompletionItemRefMode::Dereference => "*",
|
||||||
};
|
};
|
||||||
s.field("ref_match", &format!("{}@{offset:?}", prefix));
|
s.field("ref_match", &format!("{prefix}@{offset:?}"));
|
||||||
}
|
}
|
||||||
if self.trigger_call_info {
|
if self.trigger_call_info {
|
||||||
s.field("trigger_call_info", &true);
|
s.field("trigger_call_info", &true);
|
||||||
|
@ -169,3 +169,15 @@ impl AssistResolveStrategy {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GroupLabel(pub String);
|
pub struct GroupLabel(pub String);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum ExprFillDefaultMode {
|
||||||
|
Todo,
|
||||||
|
Default,
|
||||||
|
Underscore,
|
||||||
|
}
|
||||||
|
impl Default for ExprFillDefaultMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,9 +5,13 @@ use hir::{
|
|||||||
sym,
|
sym,
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
FxHashMap, assists::Assist, famous_defs::FamousDefs,
|
FxHashMap,
|
||||||
imports::import_assets::item_for_path_search, source_change::SourceChange,
|
assists::{Assist, ExprFillDefaultMode},
|
||||||
syntax_helpers::tree_diff::diff, text_edit::TextEdit,
|
famous_defs::FamousDefs,
|
||||||
|
imports::import_assets::item_for_path_search,
|
||||||
|
source_change::SourceChange,
|
||||||
|
syntax_helpers::tree_diff::diff,
|
||||||
|
text_edit::TextEdit,
|
||||||
use_trivial_constructor::use_trivial_constructor,
|
use_trivial_constructor::use_trivial_constructor,
|
||||||
};
|
};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
@ -102,8 +106,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
|
|||||||
});
|
});
|
||||||
|
|
||||||
let generate_fill_expr = |ty: &Type| match ctx.config.expr_fill_default {
|
let generate_fill_expr = |ty: &Type| match ctx.config.expr_fill_default {
|
||||||
crate::ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
ExprFillDefaultMode::Todo => make::ext::expr_todo(),
|
||||||
crate::ExprFillDefaultMode::Default => {
|
ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
|
||||||
|
ExprFillDefaultMode::Default => {
|
||||||
get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo)
|
get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::ops::Not;
|
||||||
|
|
||||||
use hir::{
|
use hir::{
|
||||||
ClosureStyle, HirDisplay, ImportPathConfig,
|
ClosureStyle, HirDisplay, ImportPathConfig,
|
||||||
db::ExpandDatabase,
|
db::ExpandDatabase,
|
||||||
@ -60,9 +62,13 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||||||
|
|
||||||
let mut formatter = |_: &hir::Type| String::from("_");
|
let mut formatter = |_: &hir::Type| String::from("_");
|
||||||
|
|
||||||
let assists: Vec<Assist> = paths
|
let assists: Vec<Assist> = d
|
||||||
|
.expected
|
||||||
|
.is_unknown()
|
||||||
|
.not()
|
||||||
|
.then(|| "todo!()".to_owned())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|path| {
|
.chain(paths.into_iter().filter_map(|path| {
|
||||||
path.gen_source_code(
|
path.gen_source_code(
|
||||||
&scope,
|
&scope,
|
||||||
&mut formatter,
|
&mut formatter,
|
||||||
@ -75,7 +81,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||||||
ctx.display_target,
|
ctx.display_target,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
})
|
}))
|
||||||
.unique()
|
.unique()
|
||||||
.map(|code| Assist {
|
.map(|code| Assist {
|
||||||
id: AssistId::quick_fix("typed-hole"),
|
id: AssistId::quick_fix("typed-hole"),
|
||||||
@ -95,9 +101,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests::{
|
use crate::tests::{check_diagnostics, check_fixes_unordered, check_has_fix};
|
||||||
check_diagnostics, check_fixes_unordered, check_has_fix, check_has_single_fix,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unknown() {
|
fn unknown() {
|
||||||
@ -119,9 +123,9 @@ fn main() {
|
|||||||
if _ {}
|
if _ {}
|
||||||
//^ 💡 error: invalid `_` expression, expected type `bool`
|
//^ 💡 error: invalid `_` expression, expected type `bool`
|
||||||
let _: fn() -> i32 = _;
|
let _: fn() -> i32 = _;
|
||||||
//^ error: invalid `_` expression, expected type `fn() -> i32`
|
//^ 💡 error: invalid `_` expression, expected type `fn() -> i32`
|
||||||
let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion*
|
let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion*
|
||||||
//^ error: invalid `_` expression, expected type `fn()`
|
//^ 💡 error: invalid `_` expression, expected type `fn()`
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
@ -147,7 +151,7 @@ fn main() {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut x = t();
|
let mut x = t();
|
||||||
x = _;
|
x = _;
|
||||||
//^ error: invalid `_` expression, expected type `&str`
|
//^ 💡 error: invalid `_` expression, expected type `&str`
|
||||||
x = "";
|
x = "";
|
||||||
}
|
}
|
||||||
fn t<T>() -> T { loop {} }
|
fn t<T>() -> T { loop {} }
|
||||||
@ -308,7 +312,7 @@ fn main() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignore_impl_func_with_incorrect_return() {
|
fn ignore_impl_func_with_incorrect_return() {
|
||||||
check_has_single_fix(
|
check_fixes_unordered(
|
||||||
r#"
|
r#"
|
||||||
struct Bar {}
|
struct Bar {}
|
||||||
trait Foo {
|
trait Foo {
|
||||||
@ -323,7 +327,8 @@ fn main() {
|
|||||||
let a: i32 = 1;
|
let a: i32 = 1;
|
||||||
let c: Bar = _$0;
|
let c: Bar = _$0;
|
||||||
}"#,
|
}"#,
|
||||||
r#"
|
vec![
|
||||||
|
r#"
|
||||||
struct Bar {}
|
struct Bar {}
|
||||||
trait Foo {
|
trait Foo {
|
||||||
type Res;
|
type Res;
|
||||||
@ -337,6 +342,21 @@ fn main() {
|
|||||||
let a: i32 = 1;
|
let a: i32 = 1;
|
||||||
let c: Bar = Bar { };
|
let c: Bar = Bar { };
|
||||||
}"#,
|
}"#,
|
||||||
|
r#"
|
||||||
|
struct Bar {}
|
||||||
|
trait Foo {
|
||||||
|
type Res;
|
||||||
|
fn foo(&self) -> Self::Res;
|
||||||
|
}
|
||||||
|
impl Foo for i32 {
|
||||||
|
type Res = Self;
|
||||||
|
fn foo(&self) -> Self::Res { 1 }
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
let a: i32 = 1;
|
||||||
|
let c: Bar = todo!();
|
||||||
|
}"#,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ use hir::{
|
|||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
|
EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
|
||||||
assists::{Assist, AssistId, AssistResolveStrategy},
|
assists::{Assist, AssistId, AssistResolveStrategy, ExprFillDefaultMode},
|
||||||
base_db::{ReleaseChannel, RootQueryDb as _},
|
base_db::{ReleaseChannel, RootQueryDb as _},
|
||||||
generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup},
|
generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup},
|
||||||
imports::insert_use::InsertUseConfig,
|
imports::insert_use::InsertUseConfig,
|
||||||
@ -219,17 +219,6 @@ impl Diagnostic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub enum ExprFillDefaultMode {
|
|
||||||
Todo,
|
|
||||||
Default,
|
|
||||||
}
|
|
||||||
impl Default for ExprFillDefaultMode {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Todo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DiagnosticsConfig {
|
pub struct DiagnosticsConfig {
|
||||||
/// Whether native diagnostics are enabled.
|
/// Whether native diagnostics are enabled.
|
||||||
|
@ -3,14 +3,16 @@
|
|||||||
mod overly_long_real_world_cases;
|
mod overly_long_real_world_cases;
|
||||||
|
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
LineIndexDatabase, RootDatabase, assists::AssistResolveStrategy, base_db::SourceDatabase,
|
LineIndexDatabase, RootDatabase,
|
||||||
|
assists::{AssistResolveStrategy, ExprFillDefaultMode},
|
||||||
|
base_db::SourceDatabase,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use stdx::trim_indent;
|
use stdx::trim_indent;
|
||||||
use test_fixture::WithFixture;
|
use test_fixture::WithFixture;
|
||||||
use test_utils::{MiniCore, assert_eq_text, extract_annotations};
|
use test_utils::{MiniCore, assert_eq_text, extract_annotations};
|
||||||
|
|
||||||
use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity};
|
use crate::{DiagnosticsConfig, Severity};
|
||||||
|
|
||||||
/// Takes a multi-file input fixture with annotated cursor positions,
|
/// Takes a multi-file input fixture with annotated cursor positions,
|
||||||
/// and checks that:
|
/// and checks that:
|
||||||
@ -160,55 +162,6 @@ pub(crate) fn check_has_fix(
|
|||||||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
assert!(fix.is_some(), "no diagnostic with desired fix");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub(crate) fn check_has_single_fix(
|
|
||||||
#[rust_analyzer::rust_fixture] ra_fixture_before: &str,
|
|
||||||
#[rust_analyzer::rust_fixture] ra_fixture_after: &str,
|
|
||||||
) {
|
|
||||||
let after = trim_indent(ra_fixture_after);
|
|
||||||
|
|
||||||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
|
||||||
let mut conf = DiagnosticsConfig::test_sample();
|
|
||||||
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
|
||||||
let mut n_fixes = 0;
|
|
||||||
let fix = super::full_diagnostics(
|
|
||||||
&db,
|
|
||||||
&conf,
|
|
||||||
&AssistResolveStrategy::All,
|
|
||||||
file_position.file_id.file_id(&db),
|
|
||||||
)
|
|
||||||
.into_iter()
|
|
||||||
.find(|d| {
|
|
||||||
d.fixes
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|fixes| {
|
|
||||||
n_fixes += fixes.len();
|
|
||||||
fixes.iter().find(|fix| {
|
|
||||||
if !fix.target.contains_inclusive(file_position.offset) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let actual = {
|
|
||||||
let source_change = fix.source_change.as_ref().unwrap();
|
|
||||||
let file_id = *source_change.source_file_edits.keys().next().unwrap();
|
|
||||||
let mut actual = db.file_text(file_id).text(&db).to_string();
|
|
||||||
|
|
||||||
for (edit, snippet_edit) in source_change.source_file_edits.values() {
|
|
||||||
edit.apply(&mut actual);
|
|
||||||
if let Some(snippet_edit) = snippet_edit {
|
|
||||||
snippet_edit.apply(&mut actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actual
|
|
||||||
};
|
|
||||||
after == actual
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.is_some()
|
|
||||||
});
|
|
||||||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
|
||||||
assert!(n_fixes == 1, "Too many fixes suggested");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks that there's a diagnostic *without* fix at `$0`.
|
/// Checks that there's a diagnostic *without* fix at `$0`.
|
||||||
pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
||||||
|
@ -599,7 +599,7 @@ fn filename_and_frag_for_def(
|
|||||||
Some(name) => {
|
Some(name) => {
|
||||||
match m.attrs(db).by_key(sym::doc).find_string_value_in_tt(sym::keyword) {
|
match m.attrs(db).by_key(sym::doc).find_string_value_in_tt(sym::keyword) {
|
||||||
Some(kw) => {
|
Some(kw) => {
|
||||||
format!("keyword.{}.html", kw)
|
format!("keyword.{kw}.html")
|
||||||
}
|
}
|
||||||
None => format!("{}/index.html", name.as_str()),
|
None => format!("{}/index.html", name.as_str()),
|
||||||
}
|
}
|
||||||
|
@ -123,9 +123,9 @@ pub use ide_completion::{
|
|||||||
CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem,
|
CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem,
|
||||||
CompletionItemKind, CompletionItemRefMode, CompletionRelevance, Snippet, SnippetScope,
|
CompletionItemKind, CompletionItemRefMode, CompletionRelevance, Snippet, SnippetScope,
|
||||||
};
|
};
|
||||||
pub use ide_db::text_edit::{Indel, TextEdit};
|
|
||||||
pub use ide_db::{
|
pub use ide_db::{
|
||||||
FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind,
|
FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind,
|
||||||
|
assists::ExprFillDefaultMode,
|
||||||
base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
|
base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
|
||||||
documentation::Documentation,
|
documentation::Documentation,
|
||||||
label::Label,
|
label::Label,
|
||||||
@ -134,8 +134,9 @@ pub use ide_db::{
|
|||||||
search::{ReferenceCategory, SearchScope},
|
search::{ReferenceCategory, SearchScope},
|
||||||
source_change::{FileSystemEdit, SnippetEdit, SourceChange},
|
source_change::{FileSystemEdit, SnippetEdit, SourceChange},
|
||||||
symbol_index::Query,
|
symbol_index::Query,
|
||||||
|
text_edit::{Indel, TextEdit},
|
||||||
};
|
};
|
||||||
pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig, ExprFillDefaultMode};
|
pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig};
|
||||||
pub use ide_ssr::SsrError;
|
pub use ide_ssr::SsrError;
|
||||||
pub use span::Edition;
|
pub use span::Edition;
|
||||||
pub use syntax::{TextRange, TextSize};
|
pub use syntax::{TextRange, TextSize};
|
||||||
|
@ -451,7 +451,7 @@ mod tests {
|
|||||||
assert_eq!(x.len(), 1);
|
assert_eq!(x.len(), 1);
|
||||||
match x.into_iter().next().unwrap() {
|
match x.into_iter().next().unwrap() {
|
||||||
MonikerResult::Local { enclosing_moniker } => {
|
MonikerResult::Local { enclosing_moniker } => {
|
||||||
panic!("Unexpected local enclosed in {:?}", enclosing_moniker);
|
panic!("Unexpected local enclosed in {enclosing_moniker:?}");
|
||||||
}
|
}
|
||||||
MonikerResult::Moniker(x) => {
|
MonikerResult::Moniker(x) => {
|
||||||
assert_eq!(identifier, x.identifier.to_string());
|
assert_eq!(identifier, x.identifier.to_string());
|
||||||
|
@ -51,8 +51,8 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
|
|||||||
buf,
|
buf,
|
||||||
"Crate: {}\n",
|
"Crate: {}\n",
|
||||||
match display_name {
|
match display_name {
|
||||||
Some(it) => format!("{it}({:?})", crate_id),
|
Some(it) => format!("{it}({crate_id:?})"),
|
||||||
None => format!("{:?}", crate_id),
|
None => format!("{crate_id:?}"),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
format_to!(buf, " Root module file id: {}\n", root_file_id.index());
|
format_to!(buf, " Root module file id: {}\n", root_file_id.index());
|
||||||
|
@ -80,7 +80,7 @@ impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
|
|||||||
|
|
||||||
fn node_id(&'a self, n: &Crate) -> Id<'a> {
|
fn node_id(&'a self, n: &Crate) -> Id<'a> {
|
||||||
let id = n.as_id().as_u32();
|
let id = n.as_id().as_u32();
|
||||||
Id::new(format!("_{:?}", id)).unwrap()
|
Id::new(format!("_{id:?}")).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_shape(&'a self, _node: &Crate) -> Option<LabelText<'a>> {
|
fn node_shape(&'a self, _node: &Crate) -> Option<LabelText<'a>> {
|
||||||
|
@ -12,5 +12,5 @@ fn main() {
|
|||||||
let version_string = std::str::from_utf8(&output.stdout[..])
|
let version_string = std::str::from_utf8(&output.stdout[..])
|
||||||
.expect("rustc --version output must be UTF-8")
|
.expect("rustc --version output must be UTF-8")
|
||||||
.trim();
|
.trim();
|
||||||
println!("cargo::rustc-env=RUSTC_VERSION={}", version_string);
|
println!("cargo::rustc-env=RUSTC_VERSION={version_string}");
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ impl LoggerDb {
|
|||||||
/// it is meant to be run from outside any tracked functions.
|
/// it is meant to be run from outside any tracked functions.
|
||||||
pub(crate) fn assert_logs(&self, expected: expect_test::Expect) {
|
pub(crate) fn assert_logs(&self, expected: expect_test::Expect) {
|
||||||
let logs = std::mem::take(&mut *self.logger.logs.lock().unwrap());
|
let logs = std::mem::take(&mut *self.logger.logs.lock().unwrap());
|
||||||
expected.assert_eq(&format!("{:#?}", logs));
|
expected.assert_eq(&format!("{logs:#?}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ impl flags::AnalysisStats {
|
|||||||
UsizeWithUnderscore(dep_loc),
|
UsizeWithUnderscore(dep_loc),
|
||||||
UsizeWithUnderscore(dep_item_trees),
|
UsizeWithUnderscore(dep_item_trees),
|
||||||
);
|
);
|
||||||
eprintln!(" dependency item stats: {}", dep_item_stats);
|
eprintln!(" dependency item stats: {dep_item_stats}");
|
||||||
|
|
||||||
// FIXME(salsa-transition): bring back stats for ParseQuery (file size)
|
// FIXME(salsa-transition): bring back stats for ParseQuery (file size)
|
||||||
// and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement
|
// and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement
|
||||||
@ -295,7 +295,7 @@ impl flags::AnalysisStats {
|
|||||||
UsizeWithUnderscore(workspace_loc),
|
UsizeWithUnderscore(workspace_loc),
|
||||||
UsizeWithUnderscore(workspace_item_trees),
|
UsizeWithUnderscore(workspace_item_trees),
|
||||||
);
|
);
|
||||||
eprintln!(" usages: {}", workspace_item_stats);
|
eprintln!(" usages: {workspace_item_stats}");
|
||||||
|
|
||||||
eprintln!(" Dependencies:");
|
eprintln!(" Dependencies:");
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@ -303,7 +303,7 @@ impl flags::AnalysisStats {
|
|||||||
UsizeWithUnderscore(dep_loc),
|
UsizeWithUnderscore(dep_loc),
|
||||||
UsizeWithUnderscore(dep_item_trees),
|
UsizeWithUnderscore(dep_item_trees),
|
||||||
);
|
);
|
||||||
eprintln!(" declarations: {}", dep_item_stats);
|
eprintln!(" declarations: {dep_item_stats}");
|
||||||
|
|
||||||
let crate_def_map_time = crate_def_map_sw.elapsed();
|
let crate_def_map_time = crate_def_map_sw.elapsed();
|
||||||
eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time);
|
eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time);
|
||||||
@ -1294,7 +1294,7 @@ impl fmt::Display for UsizeWithUnderscore {
|
|||||||
let num_str = self.0.to_string();
|
let num_str = self.0.to_string();
|
||||||
|
|
||||||
if num_str.len() <= 3 {
|
if num_str.len() <= 3 {
|
||||||
return write!(f, "{}", num_str);
|
return write!(f, "{num_str}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
@ -1307,7 +1307,7 @@ impl fmt::Display for UsizeWithUnderscore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let result = result.chars().rev().collect::<String>();
|
let result = result.chars().rev().collect::<String>();
|
||||||
write!(f, "{}", result)
|
write!(f, "{result}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,10 +265,10 @@ impl flags::Scip {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !duplicate_symbol_errors.is_empty() {
|
if !duplicate_symbol_errors.is_empty() {
|
||||||
eprintln!("{}", DUPLICATE_SYMBOLS_MESSAGE);
|
eprintln!("{DUPLICATE_SYMBOLS_MESSAGE}");
|
||||||
for (source_location, symbol) in duplicate_symbol_errors {
|
for (source_location, symbol) in duplicate_symbol_errors {
|
||||||
eprintln!("{}", source_location);
|
eprintln!("{source_location}");
|
||||||
eprintln!(" Duplicate symbol: {}", symbol);
|
eprintln!(" Duplicate symbol: {symbol}");
|
||||||
eprintln!();
|
eprintln!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,14 @@ use cfg::{CfgAtom, CfgDiff};
|
|||||||
use hir::Symbol;
|
use hir::Symbol;
|
||||||
use ide::{
|
use ide::{
|
||||||
AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig,
|
AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig,
|
||||||
CompletionFieldsToResolve, DiagnosticsConfig, ExprFillDefaultMode, GenericParameterHints,
|
CompletionFieldsToResolve, DiagnosticsConfig, GenericParameterHints, HighlightConfig,
|
||||||
HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
|
HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig,
|
||||||
InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
|
JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope,
|
||||||
Snippet, SnippetScope, SourceRootId,
|
SourceRootId,
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
SnippetCap,
|
SnippetCap,
|
||||||
|
assists::ExprFillDefaultMode,
|
||||||
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
||||||
};
|
};
|
||||||
use itertools::{Either, Itertools};
|
use itertools::{Either, Itertools};
|
||||||
@ -1493,6 +1494,11 @@ impl Config {
|
|||||||
term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64,
|
term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64,
|
||||||
term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(),
|
term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(),
|
||||||
code_action_grouping: self.code_action_group(),
|
code_action_grouping: self.code_action_group(),
|
||||||
|
expr_fill_default: match self.assist_expressionFillDefault(source_root) {
|
||||||
|
ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
|
||||||
|
ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
|
||||||
|
ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,6 +1583,7 @@ impl Config {
|
|||||||
expr_fill_default: match self.assist_expressionFillDefault(source_root) {
|
expr_fill_default: match self.assist_expressionFillDefault(source_root) {
|
||||||
ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
|
ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
|
||||||
ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
|
ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
|
||||||
|
ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore,
|
||||||
},
|
},
|
||||||
snippet_cap: self.snippet_cap(),
|
snippet_cap: self.snippet_cap(),
|
||||||
insert_use: self.insert_use_config(source_root),
|
insert_use: self.insert_use_config(source_root),
|
||||||
@ -2527,6 +2534,7 @@ where
|
|||||||
enum ExprFillDefaultDef {
|
enum ExprFillDefaultDef {
|
||||||
Todo,
|
Todo,
|
||||||
Default,
|
Default,
|
||||||
|
Underscore,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -69,6 +69,9 @@ pub mod ext {
|
|||||||
pub fn expr_todo() -> ast::Expr {
|
pub fn expr_todo() -> ast::Expr {
|
||||||
expr_from_text("todo!()")
|
expr_from_text("todo!()")
|
||||||
}
|
}
|
||||||
|
pub fn expr_underscore() -> ast::Expr {
|
||||||
|
expr_from_text("_")
|
||||||
|
}
|
||||||
pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr {
|
pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr {
|
||||||
expr_from_text(&format!("{ty}::default()"))
|
expr_from_text(&format!("{ty}::default()"))
|
||||||
}
|
}
|
||||||
|
@ -728,9 +728,9 @@ fn print_debug_subtree<S: fmt::Debug>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{align}SUBTREE {delim} ",)?;
|
write!(f, "{align}SUBTREE {delim} ",)?;
|
||||||
write!(f, "{:#?}", open)?;
|
write!(f, "{open:#?}")?;
|
||||||
write!(f, " ")?;
|
write!(f, " ")?;
|
||||||
write!(f, "{:#?}", close)?;
|
write!(f, "{close:#?}")?;
|
||||||
for child in iter {
|
for child in iter {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
print_debug_token(f, level + 1, child)?;
|
print_debug_token(f, level + 1, child)?;
|
||||||
@ -855,7 +855,7 @@ impl<S> fmt::Display for Literal<S> {
|
|||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
if let Some(suffix) = &self.suffix {
|
if let Some(suffix) = &self.suffix {
|
||||||
write!(f, "{}", suffix)?;
|
write!(f, "{suffix}")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -414,7 +414,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
|
|||||||
.map(|kind| to_pascal_case(kind))
|
.map(|kind| to_pascal_case(kind))
|
||||||
.filter(|name| !defined_nodes.iter().any(|&it| it == name))
|
.filter(|name| !defined_nodes.iter().any(|&it| it == name))
|
||||||
{
|
{
|
||||||
eprintln!("Warning: node {} not defined in AST source", node);
|
eprintln!("Warning: node {node} not defined in AST source");
|
||||||
drop(node);
|
drop(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ fn collect_tests(s: &str) -> Vec<Test> {
|
|||||||
(name.to_owned(), Some(edition.to_owned()))
|
(name.to_owned(), Some(edition.to_owned()))
|
||||||
}
|
}
|
||||||
[name] => (name.to_owned(), None),
|
[name] => (name.to_owned(), None),
|
||||||
_ => panic!("invalid test name: {:?}", name),
|
_ => panic!("invalid test name: {name:?}"),
|
||||||
};
|
};
|
||||||
let text: String = edition
|
let text: String = edition
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -212,7 +212,7 @@ fn existing_tests(dir: &Path, ok: TestKind) -> Result<HashMap<String, (PathBuf,
|
|||||||
text.lines().next().and_then(|it| it.strip_prefix("// ")).map(ToOwned::to_owned);
|
text.lines().next().and_then(|it| it.strip_prefix("// ")).map(ToOwned::to_owned);
|
||||||
let test = Test { name: name.clone(), text, kind: ok, edition };
|
let test = Test { name: name.clone(), text, kind: ok, edition };
|
||||||
if let Some(old) = res.insert(name, (path, test)) {
|
if let Some(old) = res.insert(name, (path, test)) {
|
||||||
println!("Duplicate test: {:?}", old);
|
println!("Duplicate test: {old:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user