From ee9b0c89e6a35b09dea708c0c0c619e1812f290e Mon Sep 17 00:00:00 2001
From: Andrea Pretto <eulerdisk@gmail.com>
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