From ee9b0c89e6a35b09dea708c0c0c619e1812f290e Mon Sep 17 00:00:00 2001 From: Andrea Pretto Date: Fri, 8 Feb 2019 22:12:49 +0100 Subject: auto_import: struct variants for ImportAction --- crates/ra_assists/src/auto_import.rs | 151 +++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 44 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs index 14a564301..77380b816 100644 --- a/crates/ra_assists/src/auto_import.rs +++ b/crates/ra_assists/src/auto_import.rs @@ -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, -- cgit v1.2.3