mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
Replace ImportGranularity::Guess with guessing boolean flag
This commit is contained in:
parent
5fd9f6c7b9
commit
b4fe479236
10 changed files with 219 additions and 33 deletions
|
@ -26,6 +26,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
|
||||||
insert_use: InsertUseConfig {
|
insert_use: InsertUseConfig {
|
||||||
granularity: ImportGranularity::Crate,
|
granularity: ImportGranularity::Crate,
|
||||||
prefix_kind: hir::PrefixKind::Plain,
|
prefix_kind: hir::PrefixKind::Plain,
|
||||||
|
enforce_granularity: true,
|
||||||
group: true,
|
group: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
|
||||||
insert_use: InsertUseConfig {
|
insert_use: InsertUseConfig {
|
||||||
granularity: ImportGranularity::Crate,
|
granularity: ImportGranularity::Crate,
|
||||||
prefix_kind: PrefixKind::Plain,
|
prefix_kind: PrefixKind::Plain,
|
||||||
|
enforce_granularity: true,
|
||||||
group: true,
|
group: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,12 +4,14 @@ use std::cmp::Ordering;
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo,
|
algo,
|
||||||
ast::{self, make, AstNode, ModuleItemOwner, PathSegmentKind},
|
ast::{self, make, AstNode, ModuleItemOwner, PathSegmentKind, VisibilityOwner},
|
||||||
ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken,
|
ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
helpers::merge_imports::{try_merge_imports, use_tree_path_cmp, MergeBehavior},
|
helpers::merge_imports::{
|
||||||
|
common_prefix, eq_visibility, try_merge_imports, use_tree_path_cmp, MergeBehavior,
|
||||||
|
},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,8 +20,6 @@ pub use hir::PrefixKind;
|
||||||
/// How imports should be grouped into use statements.
|
/// How imports should be grouped into use statements.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ImportGranularity {
|
pub enum ImportGranularity {
|
||||||
/// Try to guess the granularity of imports on a per module basis by observing the existing imports.
|
|
||||||
Guess,
|
|
||||||
/// Do not change the granularity of any imports and preserve the original structure written by the developer.
|
/// Do not change the granularity of any imports and preserve the original structure written by the developer.
|
||||||
Preserve,
|
Preserve,
|
||||||
/// Merge imports from the same crate into a single use statement.
|
/// Merge imports from the same crate into a single use statement.
|
||||||
|
@ -33,6 +33,7 @@ pub enum ImportGranularity {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct InsertUseConfig {
|
pub struct InsertUseConfig {
|
||||||
pub granularity: ImportGranularity,
|
pub granularity: ImportGranularity,
|
||||||
|
pub enforce_granularity: bool,
|
||||||
pub prefix_kind: PrefixKind,
|
pub prefix_kind: PrefixKind,
|
||||||
pub group: bool,
|
pub group: bool,
|
||||||
}
|
}
|
||||||
|
@ -81,40 +82,88 @@ impl ImportScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guess_merge_behavior_from_scope(&self) -> Option<MergeBehavior> {
|
fn guess_granularity_from_scope(&self) -> ImportGranularityGuess {
|
||||||
|
// The idea is simple, just check each import as well as the import and its precedent together for
|
||||||
|
// whether they fulfill a granularity criteria.
|
||||||
let use_stmt = |item| match item {
|
let use_stmt = |item| match item {
|
||||||
ast::Item::Use(use_) => use_.use_tree(),
|
ast::Item::Use(use_) => {
|
||||||
|
let use_tree = use_.use_tree()?;
|
||||||
|
Some((use_tree, use_.visibility()))
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let use_stmts = match self {
|
let mut use_stmts = match self {
|
||||||
ImportScope::File(f) => f.items(),
|
ImportScope::File(f) => f.items(),
|
||||||
ImportScope::Module(m) => m.items(),
|
ImportScope::Module(m) => m.items(),
|
||||||
}
|
}
|
||||||
.filter_map(use_stmt);
|
.filter_map(use_stmt);
|
||||||
let mut res = None;
|
let mut res = ImportGranularityGuess::Unknown;
|
||||||
for tree in use_stmts {
|
let (mut prev, mut prev_vis) = match use_stmts.next() {
|
||||||
if let Some(list) = tree.use_tree_list() {
|
Some(it) => it,
|
||||||
if list.use_trees().any(|tree| tree.use_tree_list().is_some()) {
|
None => return res,
|
||||||
// double nested tree list, can only be a crate style import at this point
|
};
|
||||||
return Some(MergeBehavior::Crate);
|
loop {
|
||||||
}
|
if let Some(use_tree_list) = prev.use_tree_list() {
|
||||||
// has to be at least a module style based import, might be crate style tho so look further
|
if use_tree_list.use_trees().any(|tree| tree.use_tree_list().is_some()) {
|
||||||
res = Some(MergeBehavior::Module);
|
// Nested tree lists can only occur in crate style, or with no proper style being enforced in the file.
|
||||||
|
break ImportGranularityGuess::Crate;
|
||||||
|
} else {
|
||||||
|
// Could still be crate-style so continue looking.
|
||||||
|
res = ImportGranularityGuess::CrateOrModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
|
||||||
|
let (curr, curr_vis) = match use_stmts.next() {
|
||||||
|
Some(it) => it,
|
||||||
|
None => break res,
|
||||||
|
};
|
||||||
|
if eq_visibility(prev_vis, curr_vis.clone()) {
|
||||||
|
if let Some((prev_path, curr_path)) = prev.path().zip(curr.path()) {
|
||||||
|
if let Some(_) = common_prefix(&prev_path, &curr_path) {
|
||||||
|
if prev.use_tree_list().is_none() && curr.use_tree_list().is_none() {
|
||||||
|
// Same prefix but no use tree lists so this has to be of item style.
|
||||||
|
break ImportGranularityGuess::Item; // this overwrites CrateOrModule, technically the file doesn't adhere to anything here.
|
||||||
|
} else {
|
||||||
|
// Same prefix with item tree lists, has to be module style as it
|
||||||
|
// can't be crate style since the trees wouldn't share a prefix then.
|
||||||
|
break ImportGranularityGuess::Module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = curr;
|
||||||
|
prev_vis = curr_vis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, PartialOrd, Debug, Clone, Copy)]
|
||||||
|
enum ImportGranularityGuess {
|
||||||
|
Unknown,
|
||||||
|
Item,
|
||||||
|
Module,
|
||||||
|
Crate,
|
||||||
|
CrateOrModule,
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
||||||
pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) {
|
pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) {
|
||||||
let _p = profile::span("insert_use");
|
let _p = profile::span("insert_use");
|
||||||
let mb = match cfg.granularity {
|
let mut mb = match cfg.granularity {
|
||||||
ImportGranularity::Guess => scope.guess_merge_behavior_from_scope(),
|
|
||||||
ImportGranularity::Crate => Some(MergeBehavior::Crate),
|
ImportGranularity::Crate => Some(MergeBehavior::Crate),
|
||||||
ImportGranularity::Module => Some(MergeBehavior::Module),
|
ImportGranularity::Module => Some(MergeBehavior::Module),
|
||||||
ImportGranularity::Item | ImportGranularity::Preserve => None,
|
ImportGranularity::Item | ImportGranularity::Preserve => None,
|
||||||
};
|
};
|
||||||
|
if !cfg.enforce_granularity {
|
||||||
|
let file_granularity = scope.guess_granularity_from_scope();
|
||||||
|
mb = match file_granularity {
|
||||||
|
ImportGranularityGuess::Unknown => mb,
|
||||||
|
ImportGranularityGuess::Item => None,
|
||||||
|
ImportGranularityGuess::Module => Some(MergeBehavior::Module),
|
||||||
|
ImportGranularityGuess::Crate => Some(MergeBehavior::Crate),
|
||||||
|
ImportGranularityGuess::CrateOrModule => mb.or(Some(MergeBehavior::Crate)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let use_item =
|
let use_item =
|
||||||
make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update();
|
make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update();
|
||||||
|
|
|
@ -631,6 +631,104 @@ fn merge_last_fail3() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_empty() {
|
||||||
|
check_guess("", ImportGranularityGuess::Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_single() {
|
||||||
|
check_guess(r"use foo::{baz::{qux, quux}, bar};", ImportGranularityGuess::Crate);
|
||||||
|
check_guess(r"use foo::bar;", ImportGranularityGuess::Unknown);
|
||||||
|
check_guess(r"use foo::bar::{baz, qux};", ImportGranularityGuess::CrateOrModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_unknown() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use oof::rab::xuq;
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Unknown,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_item() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use foo::bar::qux;
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Item,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_module() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use foo::bar::{qux, quux};
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Module,
|
||||||
|
);
|
||||||
|
// this is a rather odd case, technically this file isn't following any style properly.
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use foo::{baz::{qux, quux}, bar};
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Module,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_crate_or_module() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use oof::bar::{qux, quux};
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::CrateOrModule,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_crate() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use frob::bar::baz;
|
||||||
|
use foo::{baz::{qux, quux}, bar};
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Crate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_skips_differing_vis() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
pub use foo::bar::qux;
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Unknown,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guess_grouping_matters() {
|
||||||
|
check_guess(
|
||||||
|
r"
|
||||||
|
use foo::bar::baz;
|
||||||
|
use oof::bar::baz;
|
||||||
|
use foo::bar::qux;
|
||||||
|
",
|
||||||
|
ImportGranularityGuess::Unknown,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn check(
|
fn check(
|
||||||
path: &str,
|
path: &str,
|
||||||
ra_fixture_before: &str,
|
ra_fixture_before: &str,
|
||||||
|
@ -651,7 +749,16 @@ fn check(
|
||||||
.find_map(ast::Path::cast)
|
.find_map(ast::Path::cast)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
insert_use(&file, path, InsertUseConfig { granularity, prefix_kind: PrefixKind::Plain, group });
|
insert_use(
|
||||||
|
&file,
|
||||||
|
path,
|
||||||
|
InsertUseConfig {
|
||||||
|
granularity,
|
||||||
|
enforce_granularity: true,
|
||||||
|
prefix_kind: PrefixKind::Plain,
|
||||||
|
group,
|
||||||
|
},
|
||||||
|
);
|
||||||
let result = file.as_syntax_node().to_string();
|
let result = file.as_syntax_node().to_string();
|
||||||
assert_eq_text!(ra_fixture_after, &result);
|
assert_eq_text!(ra_fixture_after, &result);
|
||||||
}
|
}
|
||||||
|
@ -686,3 +793,9 @@ fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior
|
||||||
let result = try_merge_imports(&use0, &use1, mb);
|
let result = try_merge_imports(&use0, &use1, mb);
|
||||||
assert_eq!(result.map(|u| u.to_string()), None);
|
assert_eq!(result.map(|u| u.to_string()), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_guess(ra_fixture: &str, expected: ImportGranularityGuess) {
|
||||||
|
let syntax = ast::SourceFile::parse(ra_fixture).tree().syntax().clone();
|
||||||
|
let file = super::ImportScope::from(syntax).unwrap();
|
||||||
|
assert_eq!(file.guess_granularity_from_scope(), expected);
|
||||||
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ fn recursive_merge(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses both paths until they differ, returning the common prefix of both.
|
/// Traverses both paths until they differ, returning the common prefix of both.
|
||||||
fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Path)> {
|
pub fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Path)> {
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
let mut lhs_curr = lhs.first_qualifier_or_self();
|
let mut lhs_curr = lhs.first_qualifier_or_self();
|
||||||
let mut rhs_curr = rhs.first_qualifier_or_self();
|
let mut rhs_curr = rhs.first_qualifier_or_self();
|
||||||
|
@ -289,7 +289,7 @@ fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering {
|
||||||
a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text))
|
a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool {
|
pub fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool {
|
||||||
match (vis0, vis1) {
|
match (vis0, vis1) {
|
||||||
(None, None) => true,
|
(None, None) => true,
|
||||||
// FIXME: Don't use the string representation to check for equality
|
// FIXME: Don't use the string representation to check for equality
|
||||||
|
|
|
@ -33,10 +33,12 @@ use crate::{
|
||||||
// be specified directly in `package.json`.
|
// be specified directly in `package.json`.
|
||||||
config_data! {
|
config_data! {
|
||||||
struct ConfigData {
|
struct ConfigData {
|
||||||
/// The strategy to use when inserting new imports or merging imports.
|
/// How imports should be grouped into use statements.
|
||||||
assist_importGranularity |
|
assist_importGranularity |
|
||||||
assist_importMergeBehavior |
|
assist_importMergeBehavior |
|
||||||
assist_importMergeBehaviour: ImportGranularityDef = "\"guess\"",
|
assist_importMergeBehaviour: ImportGranularityDef = "\"crate\"",
|
||||||
|
/// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.
|
||||||
|
assist_importEnforceGranularity: bool = "false",
|
||||||
/// The path structure for newly inserted paths to use.
|
/// The path structure for newly inserted paths to use.
|
||||||
assist_importPrefix: ImportPrefixDef = "\"plain\"",
|
assist_importPrefix: ImportPrefixDef = "\"plain\"",
|
||||||
/// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
|
/// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
|
||||||
|
@ -610,12 +612,12 @@ impl Config {
|
||||||
fn insert_use_config(&self) -> InsertUseConfig {
|
fn insert_use_config(&self) -> InsertUseConfig {
|
||||||
InsertUseConfig {
|
InsertUseConfig {
|
||||||
granularity: match self.data.assist_importGranularity {
|
granularity: match self.data.assist_importGranularity {
|
||||||
ImportGranularityDef::Guess => ImportGranularity::Guess,
|
|
||||||
ImportGranularityDef::Preserve => ImportGranularity::Preserve,
|
ImportGranularityDef::Preserve => ImportGranularity::Preserve,
|
||||||
ImportGranularityDef::Item => ImportGranularity::Item,
|
ImportGranularityDef::Item => ImportGranularity::Item,
|
||||||
ImportGranularityDef::Crate => ImportGranularity::Crate,
|
ImportGranularityDef::Crate => ImportGranularity::Crate,
|
||||||
ImportGranularityDef::Module => ImportGranularity::Module,
|
ImportGranularityDef::Module => ImportGranularity::Module,
|
||||||
},
|
},
|
||||||
|
enforce_granularity: self.data.assist_importEnforceGranularity,
|
||||||
prefix_kind: match self.data.assist_importPrefix {
|
prefix_kind: match self.data.assist_importPrefix {
|
||||||
ImportPrefixDef::Plain => PrefixKind::Plain,
|
ImportPrefixDef::Plain => PrefixKind::Plain,
|
||||||
ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
|
ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
|
||||||
|
@ -721,7 +723,6 @@ enum ManifestOrProjectJson {
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
enum ImportGranularityDef {
|
enum ImportGranularityDef {
|
||||||
Preserve,
|
Preserve,
|
||||||
Guess,
|
|
||||||
#[serde(alias = "none")]
|
#[serde(alias = "none")]
|
||||||
Item,
|
Item,
|
||||||
#[serde(alias = "full")]
|
#[serde(alias = "full")]
|
||||||
|
@ -891,6 +892,16 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
|
||||||
"Merge imports from the same module into a single `use` statement."
|
"Merge imports from the same module into a single `use` statement."
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"ImportGranularityDef" => set! {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["preserve", "crate", "module", "item"],
|
||||||
|
"enumDescriptions": [
|
||||||
|
"Do not change the granularity of any imports and preserve the original structure written by the developer.",
|
||||||
|
"Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.",
|
||||||
|
"Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.",
|
||||||
|
"Flatten imports so that each has its own use statement."
|
||||||
|
],
|
||||||
|
},
|
||||||
"ImportPrefixDef" => set! {
|
"ImportPrefixDef" => set! {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
|
|
@ -138,6 +138,7 @@ fn integrated_completion_benchmark() {
|
||||||
insert_use: InsertUseConfig {
|
insert_use: InsertUseConfig {
|
||||||
granularity: ImportGranularity::Crate,
|
granularity: ImportGranularity::Crate,
|
||||||
prefix_kind: hir::PrefixKind::ByCrate,
|
prefix_kind: hir::PrefixKind::ByCrate,
|
||||||
|
enforce_granularity: true,
|
||||||
group: true,
|
group: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -171,6 +172,7 @@ fn integrated_completion_benchmark() {
|
||||||
insert_use: InsertUseConfig {
|
insert_use: InsertUseConfig {
|
||||||
granularity: ImportGranularity::Crate,
|
granularity: ImportGranularity::Crate,
|
||||||
prefix_kind: hir::PrefixKind::ByCrate,
|
prefix_kind: hir::PrefixKind::ByCrate,
|
||||||
|
enforce_granularity: true,
|
||||||
group: true,
|
group: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1179,6 +1179,7 @@ mod tests {
|
||||||
insert_use: InsertUseConfig {
|
insert_use: InsertUseConfig {
|
||||||
granularity: ImportGranularity::Item,
|
granularity: ImportGranularity::Item,
|
||||||
prefix_kind: PrefixKind::Plain,
|
prefix_kind: PrefixKind::Plain,
|
||||||
|
enforce_granularity: true,
|
||||||
group: true,
|
group: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
[[rust-analyzer.assist.importMergeBehavior]]rust-analyzer.assist.importMergeBehavior (default: `"crate"`)::
|
[[rust-analyzer.assist.importGranularity]]rust-analyzer.assist.importGranularity (default: `"crate"`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
The strategy to use when inserting new imports or merging imports.
|
How imports should be grouped into use statements.
|
||||||
|
--
|
||||||
|
[[rust-analyzer.assist.importEnforceGranularity]]rust-analyzer.assist.importEnforceGranularity (default: `false`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.assist.importPrefix]]rust-analyzer.assist.importPrefix (default: `"plain"`)::
|
[[rust-analyzer.assist.importPrefix]]rust-analyzer.assist.importPrefix (default: `"plain"`)::
|
||||||
+
|
+
|
||||||
|
|
|
@ -387,23 +387,26 @@
|
||||||
"$generated-start": false,
|
"$generated-start": false,
|
||||||
"rust-analyzer.assist.importGranularity": {
|
"rust-analyzer.assist.importGranularity": {
|
||||||
"markdownDescription": "How imports should be grouped into use statements.",
|
"markdownDescription": "How imports should be grouped into use statements.",
|
||||||
"default": "guess",
|
"default": "crate",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"guess",
|
|
||||||
"preserve",
|
"preserve",
|
||||||
"crate",
|
"crate",
|
||||||
"module",
|
"module",
|
||||||
"item"
|
"item"
|
||||||
],
|
],
|
||||||
"enumDescriptions": [
|
"enumDescriptions": [
|
||||||
"Try to guess the granularity of imports on a per module basis by observing the existing imports.",
|
|
||||||
"Do not change the granularity of any imports and preserve the original structure written by the developer.",
|
"Do not change the granularity of any imports and preserve the original structure written by the developer.",
|
||||||
"Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.",
|
"Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.",
|
||||||
"Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.",
|
"Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.",
|
||||||
"Flatten imports so that each has its own use statement."
|
"Flatten imports so that each has its own use statement."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"rust-analyzer.assist.importEnforceGranularity": {
|
||||||
|
"markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.",
|
||||||
|
"default": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"rust-analyzer.assist.importPrefix": {
|
"rust-analyzer.assist.importPrefix": {
|
||||||
"markdownDescription": "The path structure for newly inserted paths to use.",
|
"markdownDescription": "The path structure for newly inserted paths to use.",
|
||||||
"default": "plain",
|
"default": "plain",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue