From 778deb38fe7e1bac8833934224d26f44eb80a6cc Mon Sep 17 00:00:00 2001
From: Kirill Bulatov <mail4score@gmail.com>
Date: Mon, 8 Mar 2021 14:59:54 +0200
Subject: [PATCH] Better strip turbofishes

---
 crates/hir_def/src/path.rs                 |  4 --
 crates/ide_db/src/helpers/import_assets.rs |  8 ++--
 crates/syntax/src/ast/make.rs              |  4 ++
 crates/syntax/src/lib.rs                   |  1 +
 crates/syntax/src/utils.rs                 | 43 ++++++++++++++++++++++
 5 files changed, 52 insertions(+), 8 deletions(-)
 create mode 100644 crates/syntax/src/utils.rs

diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 1dc085199f3..0e60dc2b63a 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -44,10 +44,6 @@ pub enum ImportAlias {
 }
 
 impl ModPath {
-    pub fn from_src_unhygienic(path: ast::Path) -> Option<ModPath> {
-        lower::lower_path(path, &Hygiene::new_unhygienic()).map(|it| it.mod_path)
-    }
-
     pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
         lower::lower_path(path, hygiene).map(|it| it.mod_path)
     }
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index 3d9df463dac..e03ccd35155 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -5,7 +5,7 @@ use hir::{
 };
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
-use syntax::{ast, AstNode, SyntaxNode};
+use syntax::{ast, utils::path_to_string_stripping_turbo_fish, AstNode, SyntaxNode};
 
 use crate::{
     items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
@@ -57,7 +57,7 @@ pub struct PathImportCandidate {
 #[derive(Debug)]
 pub struct FirstSegmentUnresolved {
     fist_segment: ast::NameRef,
-    full_qualifier: ModPath,
+    full_qualifier: ast::Path,
 }
 
 /// A name that will be used during item lookups.
@@ -310,7 +310,7 @@ fn path_applicable_imports(
         }
         Some(first_segment_unresolved) => (
             first_segment_unresolved.fist_segment.to_string(),
-            first_segment_unresolved.full_qualifier.to_string(),
+            path_to_string_stripping_turbo_fish(&first_segment_unresolved.full_qualifier),
         ),
     };
 
@@ -583,7 +583,7 @@ fn path_import_candidate(
                     ImportCandidate::Path(PathImportCandidate {
                         qualifier: Some(FirstSegmentUnresolved {
                             fist_segment: qualifier_start,
-                            full_qualifier: ModPath::from_src_unhygienic(qualifier)?,
+                            full_qualifier: qualifier,
                         }),
                         name,
                     })
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index b6c5de65884..70ba8adb487 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -91,6 +91,10 @@ pub fn path_from_segments(
     })
 }
 
+pub fn path_from_text(text: &str) -> ast::Path {
+    ast_from_text(&format!("fn main() {{ let test = {}; }}", text))
+}
+
 pub fn glob_use_tree() -> ast::UseTree {
     ast_from_text("use *;")
 }
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 11294c5b22b..09e212e8c03 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -37,6 +37,7 @@ pub mod algo;
 pub mod ast;
 #[doc(hidden)]
 pub mod fuzz;
+pub mod utils;
 
 use std::{marker::PhantomData, sync::Arc};
 
diff --git a/crates/syntax/src/utils.rs b/crates/syntax/src/utils.rs
new file mode 100644
index 00000000000..f4c02518b4c
--- /dev/null
+++ b/crates/syntax/src/utils.rs
@@ -0,0 +1,43 @@
+//! A set of utils methods to reuse on other abstraction levels
+
+use itertools::Itertools;
+
+use crate::{ast, match_ast, AstNode};
+
+pub fn path_to_string_stripping_turbo_fish(path: &ast::Path) -> String {
+    path.syntax()
+        .children()
+        .filter_map(|node| {
+            match_ast! {
+                match node {
+                    ast::PathSegment(it) => {
+                        Some(it.name_ref()?.to_string())
+                    },
+                    ast::Path(it) => {
+                        Some(path_to_string_stripping_turbo_fish(&it))
+                    },
+                    _ => None,
+                }
+            }
+        })
+        .join("::")
+}
+
+#[cfg(test)]
+mod tests {
+    use super::path_to_string_stripping_turbo_fish;
+    use crate::ast::make;
+
+    #[test]
+    fn turbofishes_are_stripped() {
+        assert_eq!("Vec", path_to_string_stripping_turbo_fish(&make::path_from_text("Vec::<i32>")),);
+        assert_eq!(
+            "Vec::new",
+            path_to_string_stripping_turbo_fish(&make::path_from_text("Vec::<i32>::new")),
+        );
+        assert_eq!(
+            "Vec::new",
+            path_to_string_stripping_turbo_fish(&make::path_from_text("Vec::new()")),
+        );
+    }
+}