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