mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
auto_import: struct variants for ImportAction
This commit is contained in:
parent
1866fb2dda
commit
ee9b0c89e6
@ -140,30 +140,64 @@ fn compare_path_segment_with_name(a: &ast::PathSegment, b: &ast::Name) -> bool {
|
||||
enum ImportAction<'a> {
|
||||
Nothing,
|
||||
// Add a brand new use statement.
|
||||
AddNewUse(
|
||||
Option<&'a SyntaxNode>, // anchor node
|
||||
bool, // true if we want to add the new statement after the anchor
|
||||
),
|
||||
|
||||
// In the following actions we keep track of how may segments matched,
|
||||
// so we can choose the best action to take.
|
||||
AddNewUse {
|
||||
anchor: Option<&'a SyntaxNode>, // anchor node
|
||||
add_after_anchor: bool,
|
||||
},
|
||||
|
||||
// To split an existing use statement creating a nested import.
|
||||
AddNestedImport(
|
||||
usize,
|
||||
&'a ast::Path, // the complete path we want to split
|
||||
Option<&'a ast::PathSegment>, // the first segment of path we want to add into the new nested list
|
||||
bool, // true if we want to add 'self' in addition to the segment
|
||||
),
|
||||
AddNestedImport {
|
||||
// how may segments matched with the target path
|
||||
common_segments: usize,
|
||||
path_to_split: &'a ast::Path,
|
||||
// the first segment of path_to_split we want to add into the new nested list
|
||||
first_segment_to_split: Option<&'a ast::PathSegment>,
|
||||
// Wether to add 'self' in addition to the target path
|
||||
add_self: bool,
|
||||
},
|
||||
// To add the target path to an existing nested import tree list.
|
||||
AddInTreeList(
|
||||
usize,
|
||||
&'a ast::UseTreeList,
|
||||
bool, // true if we want to add 'self'
|
||||
),
|
||||
AddInTreeList {
|
||||
common_segments: usize,
|
||||
// The UseTreeList where to add the target path
|
||||
tree_list: &'a ast::UseTreeList,
|
||||
add_self: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> ImportAction<'a> {
|
||||
fn add_new_use(anchor: Option<&'a SyntaxNode>, add_after_anchor: bool) -> Self {
|
||||
ImportAction::AddNewUse {
|
||||
anchor,
|
||||
add_after_anchor,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_nested_import(
|
||||
common_segments: usize,
|
||||
path_to_split: &'a ast::Path,
|
||||
first_segment_to_split: Option<&'a ast::PathSegment>,
|
||||
add_self: bool,
|
||||
) -> Self {
|
||||
ImportAction::AddNestedImport {
|
||||
common_segments,
|
||||
path_to_split,
|
||||
first_segment_to_split,
|
||||
add_self,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_in_tree_list(
|
||||
common_segments: usize,
|
||||
tree_list: &'a ast::UseTreeList,
|
||||
add_self: bool,
|
||||
) -> Self {
|
||||
ImportAction::AddInTreeList {
|
||||
common_segments,
|
||||
tree_list,
|
||||
add_self,
|
||||
}
|
||||
}
|
||||
|
||||
fn better<'b>(left: &'b ImportAction<'a>, right: &'b ImportAction<'a>) -> &'b ImportAction<'a> {
|
||||
if left.is_better(right) {
|
||||
left
|
||||
@ -175,13 +209,27 @@ impl<'a> ImportAction<'a> {
|
||||
fn is_better(&self, other: &ImportAction) -> bool {
|
||||
match (self, other) {
|
||||
(ImportAction::Nothing, _) => true,
|
||||
(ImportAction::AddInTreeList(..), ImportAction::Nothing) => false,
|
||||
(ImportAction::AddNestedImport(n, ..), ImportAction::AddInTreeList(m, ..)) => n > m,
|
||||
(ImportAction::AddInTreeList(n, ..), ImportAction::AddNestedImport(m, ..)) => n > m,
|
||||
(ImportAction::AddInTreeList(..), _) => true,
|
||||
(ImportAction::AddNestedImport(..), ImportAction::Nothing) => false,
|
||||
(ImportAction::AddNestedImport(..), _) => true,
|
||||
(ImportAction::AddNewUse(..), _) => false,
|
||||
(ImportAction::AddInTreeList { .. }, ImportAction::Nothing) => false,
|
||||
(
|
||||
ImportAction::AddNestedImport {
|
||||
common_segments: n, ..
|
||||
},
|
||||
ImportAction::AddInTreeList {
|
||||
common_segments: m, ..
|
||||
},
|
||||
) => n > m,
|
||||
(
|
||||
ImportAction::AddInTreeList {
|
||||
common_segments: n, ..
|
||||
},
|
||||
ImportAction::AddNestedImport {
|
||||
common_segments: m, ..
|
||||
},
|
||||
) => n > m,
|
||||
(ImportAction::AddInTreeList { .. }, _) => true,
|
||||
(ImportAction::AddNestedImport { .. }, ImportAction::Nothing) => false,
|
||||
(ImportAction::AddNestedImport { .. }, _) => true,
|
||||
(ImportAction::AddNewUse { .. }, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,7 +253,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
Some(path) => path,
|
||||
None => {
|
||||
// If the use item don't have a path, it means it's broken (syntax error)
|
||||
return ImportAction::AddNewUse(
|
||||
return ImportAction::add_new_use(
|
||||
current_use_tree
|
||||
.syntax()
|
||||
.ancestors()
|
||||
@ -231,7 +279,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
let right = current_path_segments.split_at(prev_len).1;
|
||||
let common = compare_path_segments(left, right);
|
||||
let mut action = match common {
|
||||
0 => ImportAction::AddNewUse(
|
||||
0 => ImportAction::add_new_use(
|
||||
// e.g: target is std::fmt and we can have
|
||||
// use foo::bar
|
||||
// We add a brand new use statement
|
||||
@ -259,7 +307,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
if has_self {
|
||||
ImportAction::Nothing
|
||||
} else {
|
||||
ImportAction::AddInTreeList(current_path_segments.len(), list, true)
|
||||
ImportAction::add_in_tree_list(current_path_segments.len(), list, true)
|
||||
}
|
||||
} else {
|
||||
// Case 1
|
||||
@ -271,7 +319,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
// use std::io;
|
||||
// We need to split.
|
||||
let segments_to_split = current_path_segments.split_at(prev_len + common).1;
|
||||
ImportAction::AddNestedImport(
|
||||
ImportAction::add_nested_import(
|
||||
prev_len + common,
|
||||
path,
|
||||
Some(segments_to_split[0]),
|
||||
@ -284,7 +332,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
// 2- use std::{ ... };
|
||||
|
||||
// fallback action
|
||||
let mut better_action = ImportAction::AddNewUse(
|
||||
let mut better_action = ImportAction::add_new_use(
|
||||
current_use_tree
|
||||
.syntax()
|
||||
.ancestors()
|
||||
@ -306,7 +354,7 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
}
|
||||
} else {
|
||||
// Case 1, split
|
||||
better_action = ImportAction::AddNestedImport(prev_len + common, path, None, true)
|
||||
better_action = ImportAction::add_nested_import(prev_len + common, path, None, true)
|
||||
}
|
||||
better_action
|
||||
}
|
||||
@ -314,7 +362,12 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
// e.g: target is std::fmt and we can have
|
||||
// use std::fmt::Debug;
|
||||
let segments_to_split = current_path_segments.split_at(prev_len + common).1;
|
||||
ImportAction::AddNestedImport(prev_len + common, path, Some(segments_to_split[0]), true)
|
||||
ImportAction::add_nested_import(
|
||||
prev_len + common,
|
||||
path,
|
||||
Some(segments_to_split[0]),
|
||||
true,
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@ -322,8 +375,8 @@ fn walk_use_tree_for_best_action<'a>(
|
||||
// If we are inside a UseTreeList adding a use statement become adding to the existing
|
||||
// tree list.
|
||||
action = match (current_parent_use_tree_list, action) {
|
||||
(Some(use_tree_list), ImportAction::AddNewUse(..)) => {
|
||||
ImportAction::AddInTreeList(prev_len, use_tree_list, false)
|
||||
(Some(use_tree_list), ImportAction::AddNewUse { .. }) => {
|
||||
ImportAction::add_in_tree_list(prev_len, use_tree_list, false)
|
||||
}
|
||||
(_, _) => action,
|
||||
};
|
||||
@ -361,26 +414,36 @@ fn best_action_for_target<'b, 'a: 'b>(
|
||||
.map(AstNode::syntax)
|
||||
.or(Some(path.syntax()));
|
||||
|
||||
return ImportAction::AddNewUse(anchor, false);
|
||||
return ImportAction::add_new_use(anchor, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_assist(action: &ImportAction, target: &[&ast::PathSegment], edit: &mut AssistBuilder) {
|
||||
match action {
|
||||
ImportAction::AddNewUse(anchor, after) => {
|
||||
make_assist_add_new_use(anchor, *after, target, edit)
|
||||
}
|
||||
ImportAction::AddInTreeList(n, tree_list_node, add_self) => {
|
||||
ImportAction::AddNewUse {
|
||||
anchor,
|
||||
add_after_anchor,
|
||||
} => make_assist_add_new_use(anchor, *add_after_anchor, target, edit),
|
||||
ImportAction::AddInTreeList {
|
||||
common_segments,
|
||||
tree_list,
|
||||
add_self,
|
||||
} => {
|
||||
// We know that the fist n segments already exists in the use statement we want
|
||||
// to modify, so we want to add only the last target.len() - n segments.
|
||||
let segments_to_add = target.split_at(*n).1;
|
||||
make_assist_add_in_tree_list(tree_list_node, segments_to_add, *add_self, edit)
|
||||
let segments_to_add = target.split_at(*common_segments).1;
|
||||
make_assist_add_in_tree_list(tree_list, segments_to_add, *add_self, edit)
|
||||
}
|
||||
ImportAction::AddNestedImport(n, path, first_segment_to_split, add_self) => {
|
||||
let segments_to_add = target.split_at(*n).1;
|
||||
ImportAction::AddNestedImport {
|
||||
common_segments,
|
||||
path_to_split,
|
||||
first_segment_to_split,
|
||||
add_self,
|
||||
} => {
|
||||
let segments_to_add = target.split_at(*common_segments).1;
|
||||
make_assist_add_nested_import(
|
||||
path,
|
||||
path_to_split,
|
||||
first_segment_to_split,
|
||||
segments_to_add,
|
||||
*add_self,
|
||||
|
Loading…
Reference in New Issue
Block a user