Repository: rust-analyzer/rust-analyzer
Pull request #3034 (2020-02-06 16:49:42)

Remove ImportLocator hack


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 88f997e7e6..f5d3f8ca23 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -101,9 +101,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "bstr"
-version = "0.2.11"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48"
+checksum = "fe8a65814ca90dfc9705af76bb6ba3c6e2534489a72270e797e603783bb4990b"
 dependencies = [
  "memchr",
 ]
@@ -505,9 +505,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.3.2"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
+checksum = "0b54058f0a6ff80b6803da8faf8997cde53872b38f4023728f6830b06cd3c0dc"
 dependencies = [
  "autocfg 1.0.0",
 ]
@@ -963,6 +963,7 @@ dependencies = [
  "ra_db",
  "ra_fmt",
  "ra_hir",
+ "ra_ide_db",
  "ra_prof",
  "ra_syntax",
  "ra_text_edit",
@@ -1165,7 +1166,6 @@ dependencies = [
  "log",
  "once_cell",
  "proptest",
- "ra_assists",
  "ra_cfg",
  "ra_db",
  "ra_fmt",
diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml
index 9d3091b919..6973038d4e 100644
--- a/crates/ra_assists/Cargo.toml
+++ b/crates/ra_assists/Cargo.toml
@@ -18,5 +18,6 @@ ra_text_edit = { path = "../ra_text_edit" }
 ra_fmt = { path = "../ra_fmt" }
 ra_prof = { path = "../ra_prof" }
 ra_db = { path = "../ra_db" }
+ra_ide_db = { path = "../ra_ide_db" }
 hir = { path = "../ra_hir", package = "ra_hir" }
 test_utils = { path = "../test_utils" }
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 2ab65ab99a..f32072dbdb 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -1,8 +1,9 @@
 //! This module defines `AssistCtx` -- the API surface that is exposed to assists.
 use either::Either;
-use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder};
-use ra_db::FileRange;
+use hir::{InFile, SourceAnalyzer, SourceBinder};
+use ra_db::{FileRange, SourceDatabase};
 use ra_fmt::{leading_indent, reindent};
+use ra_ide_db::RootDatabase;
 use ra_syntax::{
     algo::{self, find_covering_element, find_node_at_offset},
     AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
@@ -49,14 +50,14 @@ pub(crate) enum Assist {
 /// moment, because the LSP API is pretty awkward in this place, and it's much
 /// easier to just compute the edit eagerly :-)
 #[derive(Debug)]
-pub(crate) struct AssistCtx<'a, DB> {
-    pub(crate) db: &'a DB,
+pub(crate) struct AssistCtx<'a> {
+    pub(crate) db: &'a RootDatabase,
     pub(crate) frange: FileRange,
     source_file: SourceFile,
     should_compute_edit: bool,
 }
 
-impl<'a, DB> Clone for AssistCtx<'a, DB> {
+impl<'a> Clone for AssistCtx<'a> {
     fn clone(&self) -> Self {
         AssistCtx {
             db: self.db,
@@ -67,17 +68,24 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
     }
 }
 
-impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
-    pub(crate) fn with_ctx<F, T>(db: &DB, frange: FileRange, should_compute_edit: bool, f: F) -> T
+impl<'a> AssistCtx<'a> {
+    pub(crate) fn with_ctx<F, T>(
+        db: &RootDatabase,
+        frange: FileRange,
+        should_compute_edit: bool,
+        f: F,
+    ) -> T
     where
-        F: FnOnce(AssistCtx<DB>) -> T,
+        F: FnOnce(AssistCtx) -> T,
     {
         let parse = db.parse(frange.file_id);
 
         let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
         f(ctx)
     }
+}
 
+impl<'a> AssistCtx<'a> {
     pub(crate) fn add_assist(
         self,
         id: AssistId,
@@ -141,7 +149,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
     pub(crate) fn covering_element(&self) -> SyntaxElement {
         find_covering_element(self.source_file.syntax(), self.frange.range)
     }
-    pub(crate) fn source_binder(&self) -> SourceBinder<'a, DB> {
+    pub(crate) fn source_binder(&self) -> SourceBinder<'a, RootDatabase> {
         SourceBinder::new(self.db)
     }
     pub(crate) fn source_analyzer(
diff --git a/crates/ra_assists/src/assists/add_custom_impl.rs b/crates/ra_assists/src/assists/add_custom_impl.rs
index f910349670..7fdd816bf8 100644
--- a/crates/ra_assists/src/assists/add_custom_impl.rs
+++ b/crates/ra_assists/src/assists/add_custom_impl.rs
@@ -1,7 +1,7 @@
 //! FIXME: write short doc here
 
 use crate::{Assist, AssistCtx, AssistId};
-use hir::db::HirDatabase;
+
 use join_to_string::join;
 use ra_syntax::{
     ast::{self, AstNode},
@@ -29,7 +29,7 @@ const DERIVE_TRAIT: &str = "derive";
 //
 // }
 // ```
-pub(crate) fn add_custom_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
     let input = ctx.find_node_at_offset::<ast::AttrInput>()?;
     let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
 
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs
index 6d9af39055..b0d1a0a80d 100644
--- a/crates/ra_assists/src/assists/add_derive.rs
+++ b/crates/ra_assists/src/assists/add_derive.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode, AttrsOwner},
     SyntaxKind::{COMMENT, WHITESPACE},
@@ -25,7 +24,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     y: u32,
 // }
 // ```
-pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> {
     let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
     let node_start = derive_insertion_offset(&nominal)?;
     ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| {
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 2443d55415..2cb9d2f48e 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -1,4 +1,4 @@
-use hir::{db::HirDatabase, HirDisplay};
+use hir::HirDisplay;
 use ra_syntax::{
     ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
     TextRange,
@@ -21,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     let x: i32 = 92;
 // }
 // ```
-pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
     let stmt = ctx.find_node_at_offset::<LetStmt>()?;
     let expr = stmt.initializer()?;
     let pat = stmt.pat()?;
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs
index 4b326c8373..241b085fd2 100644
--- a/crates/ra_assists/src/assists/add_impl.rs
+++ b/crates/ra_assists/src/assists/add_impl.rs
@@ -1,5 +1,5 @@
 use format_buf::format;
-use hir::db::HirDatabase;
+
 use join_to_string::join;
 use ra_syntax::{
     ast::{self, AstNode, NameOwner, TypeParamsOwner},
@@ -27,7 +27,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //
 // }
 // ```
-pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
     let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
     let name = nominal.name()?;
     ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| {
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index fc038df78c..f03dddac8f 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -1,4 +1,4 @@
-use hir::{self, db::HirDatabase, ModPath};
+use hir::{self, ModPath};
 use ra_syntax::{
     ast::{self, NameOwner},
     AstNode, Direction, SmolStr,
@@ -50,7 +50,7 @@ pub fn auto_import_text_edit(
 //
 // fn process(map: HashMap<String, String>) {}
 // ```
-pub(crate) fn add_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_import(ctx: AssistCtx) -> Option<Assist> {
     let path: ast::Path = ctx.find_node_at_offset()?;
     // We don't want to mess with use statements
     if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index e4c22ad559..448697d315 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -43,7 +43,7 @@ enum AddMissingImplMembersMode {
 //
 // }
 // ```
-pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> {
     add_missing_impl_members_inner(
         ctx,
         AddMissingImplMembersMode::NoDefaultMethods,
@@ -84,7 +84,7 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
 //
 // }
 // ```
-pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> {
     add_missing_impl_members_inner(
         ctx,
         AddMissingImplMembersMode::DefaultMethodsOnly,
@@ -94,7 +94,7 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> O
 }
 
 fn add_missing_impl_members_inner(
-    ctx: AssistCtx<impl HirDatabase>,
+    ctx: AssistCtx,
     mode: AddMissingImplMembersMode,
     assist_id: &'static str,
     label: &'static str,
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index 8db63f7627..a08639311f 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -1,5 +1,5 @@
 use format_buf::format;
-use hir::{db::HirDatabase, InFile};
+use hir::InFile;
 use join_to_string::join;
 use ra_syntax::{
     ast::{
@@ -31,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
 // }
 //
 // ```
-pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> {
     let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
 
     // We want to only apply this to non-union structs with named fields
@@ -128,10 +128,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
 //
 // FIXME: change the new fn checking to a more semantic approach when that's more
 // viable (e.g. we process proc macros, etc)
-fn find_struct_impl(
-    ctx: &AssistCtx<impl HirDatabase>,
-    strukt: &ast::StructDef,
-) -> Option<Option<ast::ImplBlock>> {
+fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<ast::ImplBlock>> {
     let db = ctx.db;
     let module = strukt.syntax().ancestors().find(|node| {
         ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
index 666dce4e60..dac6280ad8 100644
--- a/crates/ra_assists/src/assists/apply_demorgan.rs
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -1,5 +1,4 @@
 use super::invert_if::invert_boolean_expression;
-use hir::db::HirDatabase;
 use ra_syntax::ast::{self, AstNode};
 
 use crate::{Assist, AssistCtx, AssistId};
@@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     if !(x == 4 && y) {}
 // }
 // ```
-pub(crate) fn apply_demorgan(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> {
     let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
     let op = expr.op_kind()?;
     let op_range = expr.op_token()?.text_range();
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs
index 2068256b08..2190510632 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/auto_import.rs
@@ -1,4 +1,4 @@
-use hir::{db::HirDatabase, ModPath};
+use hir::ModPath;
 use ra_syntax::{
     ast::{self, AstNode},
     SyntaxNode,
@@ -6,8 +6,9 @@ use ra_syntax::{
 
 use crate::{
     assist_ctx::{ActionBuilder, Assist, AssistCtx},
-    auto_import_text_edit, AssistId, ImportsLocator,
+    auto_import_text_edit, AssistId,
 };
+use ra_ide_db::imports_locator::ImportsLocatorIde;
 
 // Assist: auto_import
 //
@@ -26,10 +27,7 @@ use crate::{
 //     let map = HashMap<|>::new();
 // }
 // ```
-pub(crate) fn auto_import<F: ImportsLocator>(
-    ctx: AssistCtx<impl HirDatabase>,
-    imports_locator: &mut F,
-) -> Option<Assist> {
+pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
     let path_to_import: ast::Path = ctx.find_node_at_offset()?;
     let path_to_import_syntax = path_to_import.syntax();
     if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
@@ -52,6 +50,8 @@ pub(crate) fn auto_import<F: ImportsLocator>(
         return None;
     }
 
+    let mut imports_locator = ImportsLocatorIde::new(ctx.db);
+
     let proposed_imports = imports_locator
         .find_imports(&name_to_import)
         .into_iter()
@@ -81,16 +81,12 @@ fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode)
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::helpers::{
-        check_assist_with_imports_locator, check_assist_with_imports_locator_not_applicable,
-        TestImportsLocator,
-    };
+    use crate::helpers::{check_assist, check_assist_not_applicable};
 
     #[test]
     fn applicable_when_found_an_import() {
-        check_assist_with_imports_locator(
+        check_assist(
             auto_import,
-            TestImportsLocator::new,
             r"
             <|>PubStruct
 
@@ -112,9 +108,8 @@ mod tests {
 
     #[test]
     fn auto_imports_are_merged() {
-        check_assist_with_imports_locator(
+        check_assist(
             auto_import,
-            TestImportsLocator::new,
             r"
             use PubMod::PubStruct1;
 
@@ -148,9 +143,8 @@ mod tests {
 
     #[test]
     fn applicable_when_found_multiple_imports() {
-        check_assist_with_imports_locator(
+        check_assist(
             auto_import,
-            TestImportsLocator::new,
             r"
             PubSt<|>ruct
 
@@ -184,9 +178,8 @@ mod tests {
 
     #[test]
     fn not_applicable_for_already_imported_types() {
-        check_assist_with_imports_locator_not_applicable(
+        check_assist_not_applicable(
             auto_import,
-            TestImportsLocator::new,
             r"
             use PubMod::PubStruct;
 
@@ -201,9 +194,8 @@ mod tests {
 
     #[test]
     fn not_applicable_for_types_with_private_paths() {
-        check_assist_with_imports_locator_not_applicable(
+        check_assist_not_applicable(
             auto_import,
-            TestImportsLocator::new,
             r"
             PrivateStruct<|>
 
@@ -216,9 +208,8 @@ mod tests {
 
     #[test]
     fn not_applicable_when_no_imports_found() {
-        check_assist_with_imports_locator_not_applicable(
+        check_assist_not_applicable(
             auto_import,
-            TestImportsLocator::new,
             "
             PubStruct<|>",
         );
@@ -226,9 +217,8 @@ mod tests {
 
     #[test]
     fn not_applicable_in_import_statements() {
-        check_assist_with_imports_locator_not_applicable(
+        check_assist_not_applicable(
             auto_import,
-            TestImportsLocator::new,
             r"
             use PubStruct<|>;
 
@@ -240,9 +230,8 @@ mod tests {
 
     #[test]
     fn function_import() {
-        check_assist_with_imports_locator(
+        check_assist(
             auto_import,
-            TestImportsLocator::new,
             r"
             test_function<|>
 
diff --git a/crates/ra_assists/src/assists/change_visibility.rs b/crates/ra_assists/src/assists/change_visibility.rs
index fd766bb460..f325b6f922 100644
--- a/crates/ra_assists/src/assists/change_visibility.rs
+++ b/crates/ra_assists/src/assists/change_visibility.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, NameOwner, VisibilityOwner},
     AstNode,
@@ -22,14 +21,14 @@ use crate::{Assist, AssistCtx, AssistId};
 // ```
 // pub(crate) fn frobnicate() {}
 // ```
-pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn change_visibility(ctx: AssistCtx) -> Option<Assist> {
     if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
         return change_vis(ctx, vis);
     }
     add_vis(ctx)
 }
 
-fn add_vis(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+fn add_vis(ctx: AssistCtx) -> Option<Assist> {
     let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
         T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
         _ => false,
@@ -75,7 +74,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
         .unwrap_or_else(|| node.text_range().start())
 }
 
-fn change_vis(ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
+fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> {
     if vis.syntax().text() == "pub" {
         return ctx.add_assist(
             AssistId("change_visibility"),
diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs
index 487ee9eef2..7d510b0552 100644
--- a/crates/ra_assists/src/assists/early_return.rs
+++ b/crates/ra_assists/src/assists/early_return.rs
@@ -1,6 +1,5 @@
 use std::{iter::once, ops::RangeInclusive};
 
-use hir::db::HirDatabase;
 use ra_syntax::{
     algo::replace_children,
     ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
@@ -36,7 +35,7 @@ use crate::{
 //     bar();
 // }
 // ```
-pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
     let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
     if if_expr.else_branch().is_some() {
         return None;
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index 01758d23aa..0908fc2469 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -31,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     }
 // }
 // ```
-pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> {
     let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
     let match_arm_list = match_expr.match_arm_list()?;
 
diff --git a/crates/ra_assists/src/assists/flip_binexpr.rs b/crates/ra_assists/src/assists/flip_binexpr.rs
index 2074087cd0..bfcc09e909 100644
--- a/crates/ra_assists/src/assists/flip_binexpr.rs
+++ b/crates/ra_assists/src/assists/flip_binexpr.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::ast::{AstNode, BinExpr, BinOp};
 
 use crate::{Assist, AssistCtx, AssistId};
@@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     let _ = 2 + 90;
 // }
 // ```
-pub(crate) fn flip_binexpr(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> {
     let expr = ctx.find_node_at_offset::<BinExpr>()?;
     let lhs = expr.lhs()?.syntax().clone();
     let rhs = expr.rhs()?.syntax().clone();
diff --git a/crates/ra_assists/src/assists/flip_comma.rs b/crates/ra_assists/src/assists/flip_comma.rs
index dd0c405eda..1dacf29f83 100644
--- a/crates/ra_assists/src/assists/flip_comma.rs
+++ b/crates/ra_assists/src/assists/flip_comma.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{algo::non_trivia_sibling, Direction, T};
 
 use crate::{Assist, AssistCtx, AssistId};
@@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     ((3, 4), (1, 2));
 // }
 // ```
-pub(crate) fn flip_comma(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
     let comma = ctx.find_token_at_offset(T![,])?;
     let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
     let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
diff --git a/crates/ra_assists/src/assists/flip_trait_bound.rs b/crates/ra_assists/src/assists/flip_trait_bound.rs
index 50b3fa4927..f56769624e 100644
--- a/crates/ra_assists/src/assists/flip_trait_bound.rs
+++ b/crates/ra_assists/src/assists/flip_trait_bound.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     algo::non_trivia_sibling,
     ast::{self, AstNode},
@@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
 // ```
 // fn foo<T: Copy + Clone>() { }
 // ```
-pub(crate) fn flip_trait_bound(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> {
     // We want to replicate the behavior of `flip_binexpr` by only suggesting
     // the assist when the cursor is on a `+`
     let plus = ctx.find_token_at_offset(T![+])?;
diff --git a/crates/ra_assists/src/assists/inline_local_variable.rs b/crates/ra_assists/src/assists/inline_local_variable.rs
index 83527d9040..91b588243e 100644
--- a/crates/ra_assists/src/assists/inline_local_variable.rs
+++ b/crates/ra_assists/src/assists/inline_local_variable.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode, AstToken},
     TextRange,
@@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     (1 + 2) * 4;
 // }
 // ```
-pub(crate) fn inline_local_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
     let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
     let bind_pat = match let_stmt.pat()? {
         ast::Pat::BindPat(pat) => pat,
diff --git a/crates/ra_assists/src/assists/introduce_variable.rs b/crates/ra_assists/src/assists/introduce_variable.rs
index 19e211e0f0..7312ce6871 100644
--- a/crates/ra_assists/src/assists/introduce_variable.rs
+++ b/crates/ra_assists/src/assists/introduce_variable.rs
@@ -1,5 +1,4 @@
 use format_buf::format;
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode},
     SyntaxKind::{
@@ -28,7 +27,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     var_name * 4;
 // }
 // ```
-pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
     if ctx.frange.range.is_empty() {
         return None;
     }
diff --git a/crates/ra_assists/src/assists/invert_if.rs b/crates/ra_assists/src/assists/invert_if.rs
index 16352c0405..694c3642c8 100644
--- a/crates/ra_assists/src/assists/invert_if.rs
+++ b/crates/ra_assists/src/assists/invert_if.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::ast::{self, AstNode};
 use ra_syntax::T;
 
@@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
 // }
 // ```
 
-pub(crate) fn invert_if(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
     let if_keyword = ctx.find_token_at_offset(T![if])?;
     let expr = ast::IfExpr::cast(if_keyword.parent())?;
     let if_range = if_keyword.text_range();
diff --git a/crates/ra_assists/src/assists/merge_match_arms.rs b/crates/ra_assists/src/assists/merge_match_arms.rs
index 64c9379da1..670614dd83 100644
--- a/crates/ra_assists/src/assists/merge_match_arms.rs
+++ b/crates/ra_assists/src/assists/merge_match_arms.rs
@@ -1,6 +1,5 @@
 use std::iter::successors;
 
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode},
     Direction, TextUnit,
@@ -32,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId, TextRange};
 //     }
 // }
 // ```
-pub(crate) fn merge_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
     let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?;
     // Don't try to handle arms with guards for now - can add support for this later
     if current_arm.guard().is_some() {
diff --git a/crates/ra_assists/src/assists/move_bounds.rs b/crates/ra_assists/src/assists/move_bounds.rs
index 355adddc36..90793b5fc3 100644
--- a/crates/ra_assists/src/assists/move_bounds.rs
+++ b/crates/ra_assists/src/assists/move_bounds.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
     SyntaxElement,
@@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     f(x)
 // }
 // ```
-pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
     let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
 
     let mut type_params = type_param_list.type_params();
diff --git a/crates/ra_assists/src/assists/move_guard.rs b/crates/ra_assists/src/assists/move_guard.rs
index 41a31e6775..2b91ce7c4d 100644
--- a/crates/ra_assists/src/assists/move_guard.rs
+++ b/crates/ra_assists/src/assists/move_guard.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast,
     ast::{AstNode, AstToken, IfExpr, MatchArm},
@@ -32,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     }
 // }
 // ```
-pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> {
     let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
     let guard = match_arm.guard()?;
     let space_before_guard = guard.syntax().prev_sibling_or_token();
@@ -89,7 +88,7 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx<impl HirDatabase>) -> Option
 //     }
 // }
 // ```
-pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
     let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
     let last_match_pat = match_arm.pats().last()?;
 
diff --git a/crates/ra_assists/src/assists/raw_string.rs b/crates/ra_assists/src/assists/raw_string.rs
index e79c51673c..2c0a1e1265 100644
--- a/crates/ra_assists/src/assists/raw_string.rs
+++ b/crates/ra_assists/src/assists/raw_string.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast, AstToken,
     SyntaxKind::{RAW_STRING, STRING},
@@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     r#"Hello, World!"#;
 // }
 // ```
-pub(crate) fn make_raw_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> {
     let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
     let value = token.value()?;
     ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| {
@@ -51,7 +50,7 @@ pub(crate) fn make_raw_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
 //     "Hello, \"World!\"";
 // }
 // ```
-pub(crate) fn make_usual_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> {
     let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
     let value = token.value()?;
     ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| {
@@ -77,7 +76,7 @@ pub(crate) fn make_usual_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
 //     r##"Hello, World!"##;
 // }
 // ```
-pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> {
     let token = ctx.find_token_at_offset(RAW_STRING)?;
     ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| {
         edit.target(token.text_range());
@@ -101,7 +100,7 @@ pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
 //     r"Hello, World!";
 // }
 // ```
-pub(crate) fn remove_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn remove_hash(ctx: AssistCtx) -> Option<Assist> {
     let token = ctx.find_token_at_offset(RAW_STRING)?;
     let text = token.text().as_str();
     if text.starts_with("r\"") {
diff --git a/crates/ra_assists/src/assists/remove_dbg.rs b/crates/ra_assists/src/assists/remove_dbg.rs
index cf211ab840..5085649b42 100644
--- a/crates/ra_assists/src/assists/remove_dbg.rs
+++ b/crates/ra_assists/src/assists/remove_dbg.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode},
     TextUnit, T,
@@ -21,7 +20,7 @@ use crate::{Assist, AssistCtx, AssistId};
 //     92;
 // }
 // ```
-pub(crate) fn remove_dbg(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> {
     let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
 
     if !is_valid_macrocall(&macro_call, "dbg")? {
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
index c8b13b7b38..e6cd50bc12 100644
--- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
@@ -1,4 +1,3 @@
-use hir::db::HirDatabase;
 use ra_fmt::unwrap_trivial_block;
 use ra_syntax::{
     ast::{self, make},
@@ -34,7 +33,7 @@ use ast::edit::IndentLevel;
 //     }
 // }
 // ```
-pub(crate) fn replace_if_let_with_match(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
     let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
     let cond = if_expr.condition()?;
     let pat = cond.pat()?;
diff --git a/crates/ra_assists/src/assists/split_import.rs b/crates/ra_assists/src/assists/split_import.rs
index 6038c48587..2c3f07a79d 100644
--- a/crates/ra_assists/src/assists/split_import.rs
+++ b/crates/ra_assists/src/assists/split_import.rs
@@ -1,6 +1,5 @@
 use std::iter::successors;
 
-use hir::db::HirDatabase;
 use ra_syntax::{ast, AstNode, TextUnit, T};
 
 use crate::{Assist, AssistCtx, AssistId};
@@ -16,7 +15,7 @@ use crate::{Assist, AssistCtx, AssistId};
 // ```
 // use std::{collections::HashMap};
 // ```
-pub(crate) fn split_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> {
     let colon_colon = ctx.find_token_at_offset(T![::])?;
     let path = ast::Path::cast(colon_colon.parent())?;
     let top_path = successors(Some(path), |it| it.parent_path()).last()?;
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 625ebc4a2d..1343043ddf 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -9,13 +9,11 @@ mod assist_ctx;
 mod marks;
 #[cfg(test)]
 mod doc_tests;
-#[cfg(test)]
-mod test_db;
 pub mod ast_transform;
 
 use either::Either;
-use hir::{db::HirDatabase, ModuleDef};
 use ra_db::FileRange;
+use ra_ide_db::RootDatabase;
 use ra_syntax::{TextRange, TextUnit};
 use ra_text_edit::TextEdit;
 
@@ -61,10 +59,7 @@ impl ResolvedAssist {
 ///
 /// Assists are returned in the "unresolved" state, that is only labels are
 /// returned, without actual edits.
-pub fn applicable_assists<H>(db: &H, range: FileRange) -> Vec<AssistLabel>
-where
-    H: HirDatabase + 'static,
-{
+pub fn applicable_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabel> {
     AssistCtx::with_ctx(db, range, false, |ctx| {
         assists::all()
             .iter()
@@ -77,59 +72,11 @@ where
     })
 }
 
-/// A functionality for locating imports for the given name.
-///
-/// Currently has to be a trait with the real implementation provided by the ra_ide_api crate,
-/// due to the search functionality located there.
-/// Later, this trait should be removed completely and the search functionality moved to a separate crate,
-/// accessible from the ra_assists crate.
-pub trait ImportsLocator {
-    /// Finds all imports for the given name and the module that contains this name.
-    fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef>;
-}
-
-/// Return all the assists applicable at the given position
-/// and additional assists that need the imports locator functionality to work.
-///
-/// Assists are returned in the "resolved" state, that is with edit fully
-/// computed.
-pub fn assists_with_imports_locator<H, F>(
-    db: &H,
-    range: FileRange,
-    mut imports_locator: F,
-) -> Vec<ResolvedAssist>
-where
-    H: HirDatabase + 'static,
-    F: ImportsLocator,
-{
-    AssistCtx::with_ctx(db, range, true, |ctx| {
-        let mut assists = assists::all()
-            .iter()
-            .map(|f| f(ctx.clone()))
-            .chain(
-                assists::all_with_imports_locator()
-                    .iter()
-                    .map(|f| f(ctx.clone(), &mut imports_locator)),
-            )
-            .filter_map(std::convert::identity)
-            .map(|a| match a {
-                Assist::Resolved { assist } => assist,
-                Assist::Unresolved { .. } => unreachable!(),
-            })
-            .collect();
-        sort_assists(&mut assists);
-        assists
-    })
-}
-
 /// Return all the assists applicable at the given position.
 ///
 /// Assists are returned in the "resolved" state, that is with edit fully
 /// computed.
-pub fn assists<H>(db: &H, range: FileRange) -> Vec<ResolvedAssist>
-where
-    H: HirDatabase + 'static,
-{
+pub fn assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> {
     AssistCtx::with_ctx(db, range, true, |ctx| {
         let mut a = assists::all()
             .iter()
@@ -155,8 +102,7 @@ fn sort_assists(assists: &mut Vec<ResolvedAssist>) {
 }
 
 mod assists {
-    use crate::{Assist, AssistCtx, ImportsLocator};
-    use hir::db::HirDatabase;
+    use crate::{Assist, AssistCtx};
 
     mod add_derive;
     mod add_explicit_type;
@@ -184,7 +130,7 @@ mod assists {
     mod move_bounds;
     mod early_return;
 
-    pub(crate) fn all<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
+    pub(crate) fn all() -> &'static [fn(AssistCtx) -> Option<Assist>] {
         &[
             add_derive::add_derive,
             add_explicit_type::add_explicit_type,
@@ -215,79 +161,34 @@ mod assists {
             raw_string::make_usual_string,
             raw_string::remove_hash,
             early_return::convert_to_guarded_return,
+            auto_import::auto_import,
         ]
     }
-
-    pub(crate) fn all_with_imports_locator<'a, DB: HirDatabase, F: ImportsLocator>(
-    ) -> &'a [fn(AssistCtx<DB>, &mut F) -> Option<Assist>] {
-        &[auto_import::auto_import]
-    }
 }
 
 #[cfg(test)]
 mod helpers {
-    use hir::db::DefDatabase;
-    use ra_db::{fixture::WithFixture, FileId, FileRange};
-    use ra_syntax::TextRange;
-    use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
-
-    use crate::{test_db::TestDB, Assist, AssistCtx, ImportsLocator};
     use std::sync::Arc;
 
-    // FIXME remove the `ModuleDefId` reexport from `ra_hir` when this gets removed.
-    pub(crate) struct TestImportsLocator {
-        db: Arc<TestDB>,
-        test_file_id: FileId,
-    }
-
-    impl TestImportsLocator {
-        pub(crate) fn new(db: Arc<TestDB>, test_file_id: FileId) -> Self {
-            TestImportsLocator { db, test_file_id }
-        }
-    }
+    use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
+    use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
+    use ra_syntax::TextRange;
+    use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
 
-    impl ImportsLocator for TestImportsLocator {
-        fn find_imports(&mut self, name_to_import: &str) -> Vec<hir::ModuleDef> {
-            let crate_def_map = self.db.crate_def_map(self.db.test_crate());
-            let mut findings = Vec::new();
-
-            let mut module_ids_to_process =
-                crate_def_map.modules_for_file(self.test_file_id).collect::<Vec<_>>();
-
-            while !module_ids_to_process.is_empty() {
-                let mut more_ids_to_process = Vec::new();
-                for local_module_id in module_ids_to_process.drain(..) {
-                    for (name, namespace_data) in
-                        crate_def_map[local_module_id].scope.entries_without_primitives()
-                    {
-                        let found_a_match = &name.to_string() == name_to_import;
-                        vec![namespace_data.types, namespace_data.values]
-                            .into_iter()
-                            .filter_map(std::convert::identity)
-                            .for_each(|(module_def_id, _)| {
-                                if found_a_match {
-                                    findings.push(module_def_id.into());
-                                }
-                                if let hir::ModuleDefId::ModuleId(module_id) = module_def_id {
-                                    more_ids_to_process.push(module_id.local_id);
-                                }
-                            });
-                    }
-                }
-                module_ids_to_process = more_ids_to_process;
-            }
+    use crate::{Assist, AssistCtx};
 
-            findings
-        }
+    pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
+        let (mut db, file_id) = RootDatabase::with_single_file(text);
+        // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
+        // but it looks like this might need specialization? :(
+        let local_roots = vec![db.file_source_root(file_id)];
+        db.set_local_roots(Arc::new(local_roots));
+        (db, file_id)
     }
 
-    pub(crate) fn check_assist(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
-        before: &str,
-        after: &str,
-    ) {
+    pub(crate) fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
         let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange =
             FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
         let assist =
@@ -309,45 +210,13 @@ mod helpers {
         assert_eq_text!(after, &actual);
     }
 
-    pub(crate) fn check_assist_with_imports_locator<F: ImportsLocator>(
-        assist: fn(AssistCtx<TestDB>, &mut F) -> Option<Assist>,
-        imports_locator_provider: fn(db: Arc<TestDB>, file_id: FileId) -> F,
-        before: &str,
-        after: &str,
-    ) {
-        let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
-        let db = Arc::new(db);
-        let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id);
-        let frange =
-            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
-        let assist =
-            AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator))
-                .expect("code action is not applicable");
-        let action = match assist {
-            Assist::Unresolved { .. } => unreachable!(),
-            Assist::Resolved { assist } => assist.get_first_action(),
-        };
-
-        let actual = action.edit.apply(&before);
-        let actual_cursor_pos = match action.cursor_position {
-            None => action
-                .edit
-                .apply_to_offset(before_cursor_pos)
-                .expect("cursor position is affected by the edit"),
-            Some(off) => off,
-        };
-        let actual = add_cursor(&actual, actual_cursor_pos);
-        assert_eq_text!(after, &actual);
-    }
-
     pub(crate) fn check_assist_range(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
+        assist: fn(AssistCtx) -> Option<Assist>,
         before: &str,
         after: &str,
     ) {
         let (range, before) = extract_range(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange = FileRange { file_id, range };
         let assist =
             AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
@@ -364,12 +233,12 @@ mod helpers {
     }
 
     pub(crate) fn check_assist_target(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
+        assist: fn(AssistCtx) -> Option<Assist>,
         before: &str,
         target: &str,
     ) {
         let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange =
             FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
         let assist =
@@ -384,12 +253,12 @@ mod helpers {
     }
 
     pub(crate) fn check_assist_range_target(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
+        assist: fn(AssistCtx) -> Option<Assist>,
         before: &str,
         target: &str,
     ) {
         let (range, before) = extract_range(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange = FileRange { file_id, range };
         let assist =
             AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
@@ -403,39 +272,23 @@ mod helpers {
     }
 
     pub(crate) fn check_assist_not_applicable(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
+        assist: fn(AssistCtx) -> Option<Assist>,
         before: &str,
     ) {
         let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange =
             FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
         let assist = AssistCtx::with_ctx(&db, frange, true, assist);
         assert!(assist.is_none());
     }
 
-    pub(crate) fn check_assist_with_imports_locator_not_applicable<F: ImportsLocator>(
-        assist: fn(AssistCtx<TestDB>, &mut F) -> Option<Assist>,
-        imports_locator_provider: fn(db: Arc<TestDB>, file_id: FileId) -> F,
-        before: &str,
-    ) {
-        let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
-        let db = Arc::new(db);
-        let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id);
-        let frange =
-            FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
-        let assist =
-            AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator));
-        assert!(assist.is_none());
-    }
-
     pub(crate) fn check_assist_range_not_applicable(
-        assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
+        assist: fn(AssistCtx) -> Option<Assist>,
         before: &str,
     ) {
         let (range, before) = extract_range(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = with_single_file(&before);
         let frange = FileRange { file_id, range };
         let assist = AssistCtx::with_ctx(&db, frange, true, assist);
         assert!(assist.is_none());
@@ -444,17 +297,17 @@ mod helpers {
 
 #[cfg(test)]
 mod tests {
-    use ra_db::{fixture::WithFixture, FileRange};
+    use ra_db::FileRange;
     use ra_syntax::TextRange;
     use test_utils::{extract_offset, extract_range};
 
-    use crate::test_db::TestDB;
+    use crate::helpers;
 
     #[test]
     fn assist_order_field_struct() {
         let before = "struct Foo { <|>bar: u32 }";
         let (before_cursor_pos, before) = extract_offset(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = helpers::with_single_file(&before);
         let frange =
             FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
         let assists = super::assists(&db, frange);
@@ -478,7 +331,7 @@ mod tests {
             }
         }";
         let (range, before) = extract_range(before);
-        let (db, file_id) = TestDB::with_single_file(&before);
+        let (db, file_id) = helpers::with_single_file(&before);
         let frange = FileRange { file_id, range };
         let assists = super::assists(&db, frange);
         let mut assists = assists.iter();
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs
index 4a7d8cfa95..c3b2c638b6 100644
--- a/crates/ra_ide/src/assists.rs
+++ b/crates/ra_ide/src/assists.rs
@@ -3,7 +3,7 @@
 use either::Either;
 use ra_assists::{AssistAction, AssistLabel};
 use ra_db::{FilePosition, FileRange};
-use ra_ide_db::{imports_locator::ImportsLocatorIde, RootDatabase};
+use ra_ide_db::RootDatabase;
 
 use crate::{FileId, SourceChange, SourceFileEdit};
 
@@ -17,7 +17,7 @@ pub struct Assist {
 }
 
 pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
-    ra_assists::assists_with_imports_locator(db, frange, ImportsLocatorIde::new(db))
+    ra_assists::assists(db, frange)
         .into_iter()
         .map(|assist| {
             let file_id = frange.file_id;
diff --git a/crates/ra_ide_db/Cargo.toml b/crates/ra_ide_db/Cargo.toml
index 1b7905eb3d..716e88bc1b 100644
--- a/crates/ra_ide_db/Cargo.toml
+++ b/crates/ra_ide_db/Cargo.toml
@@ -32,7 +32,6 @@ ra_cfg = { path = "../ra_cfg" }
 ra_fmt = { path = "../ra_fmt" }
 ra_prof = { path = "../ra_prof" }
 test_utils = { path = "../test_utils" }
-ra_assists = { path = "../ra_assists" }
 
 # ra_ide should depend only on the top-level `hir` package. if you need
 # something from some `hir_xxx` subpackage, reexport the API via `hir`.
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index cee6dde8e0..7889067232 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -92,7 +92,7 @@ pub fn classify_name(
             ast::FnDef(it) => {
                 let src = name.with_value(it);
                 let def: hir::Function = sb.to_def(src)?;
-                if parent.parent().and_then(ast::ItemList::cast).is_some() {
+                if parent.parent().and_then(ast::ItemList::cast).map_or(false, |it| it.syntax().parent().and_then(ast::Module::cast).is_none()) {
                     Some(from_assoc_item(sb.db, def.into()))
                 } else {
                     Some(from_module_def(sb.db, def.into(), None))
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs
index 21e6376085..d77fc53f3a 100644
--- a/crates/ra_ide_db/src/imports_locator.rs
+++ b/crates/ra_ide_db/src/imports_locator.rs
@@ -2,7 +2,6 @@
 //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module.
 
 use hir::{db::HirDatabase, ModuleDef, SourceBinder};
-use ra_assists::ImportsLocator;
 use ra_prof::profile;
 use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
 
@@ -22,29 +21,7 @@ impl<'a> ImportsLocatorIde<'a> {
         Self { source_binder: SourceBinder::new(db) }
     }
 
-    fn get_name_definition(
-        &mut self,
-        db: &impl HirDatabase,
-        import_candidate: &FileSymbol,
-    ) -> Option<NameKind> {
-        let _p = profile("get_name_definition");
-        let file_id = import_candidate.file_id.into();
-        let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
-        let candidate_name_node = if candidate_node.kind() != NAME {
-            candidate_node.children().find(|it| it.kind() == NAME)?
-        } else {
-            candidate_node
-        };
-        classify_name(
-            &mut self.source_binder,
-            hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
-        )
-        .map(|it| it.kind)
-    }
-}
-
-impl ImportsLocator for ImportsLocatorIde<'_> {
-    fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
+    pub fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
         let _p = profile("search_for_imports");
         let db = self.source_binder.db;
 
@@ -72,4 +49,24 @@ impl ImportsLocator for ImportsLocatorIde<'_> {
             })
             .collect()
     }
+
+    fn get_name_definition(
+        &mut self,
+        db: &impl HirDatabase,
+        import_candidate: &FileSymbol,
+    ) -> Option<NameKind> {
+        let _p = profile("get_name_definition");
+        let file_id = import_candidate.file_id.into();
+        let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
+        let candidate_name_node = if candidate_node.kind() != NAME {
+            candidate_node.children().find(|it| it.kind() == NAME)?
+        } else {
+            candidate_node
+        };
+        classify_name(
+            &mut self.source_binder,
+            hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
+        )
+        .map(|it| it.kind)
+    }
 }


Test patch:
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs
index 65d51428bb..370b642255 100644
--- a/crates/ra_assists/src/doc_tests.rs
+++ b/crates/ra_assists/src/doc_tests.rs
@@ -8,7 +8,7 @@ mod generated;
 use ra_db::{fixture::WithFixture, FileRange};
 use test_utils::{assert_eq_text, extract_range_or_offset};
 
-use crate::test_db::TestDB;
+use ra_ide_db::RootDatabase;
 
 fn check(assist_id: &str, before: &str, after: &str) {
     // FIXME we cannot get the imports search functionality here yet, but still need to generate a test and a doc for an assist
@@ -16,7 +16,7 @@ fn check(assist_id: &str, before: &str, after: &str) {
         return;
     }
     let (selection, before) = extract_range_or_offset(before);
-    let (db, file_id) = TestDB::with_single_file(&before);
+    let (db, file_id) = RootDatabase::with_single_file(&before);
     let frange = FileRange { file_id, range: selection.into() };
 
     let assist = crate::assists(&db, frange)
diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs
deleted file mode 100644
index d5249f3088..0000000000
--- a/crates/ra_assists/src/test_db.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! Database used for testing `ra_assists`.
-
-use std::sync::Arc;
-
-use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
-
-#[salsa::database(
-    ra_db::SourceDatabaseExtStorage,
-    ra_db::SourceDatabaseStorage,
-    hir::db::InternDatabaseStorage,
-    hir::db::AstDatabaseStorage,
-    hir::db::DefDatabaseStorage,
-    hir::db::HirDatabaseStorage
-)]
-#[derive(Debug, Default)]
-pub struct TestDB {
-    runtime: salsa::Runtime<TestDB>,
-}
-
-impl salsa::Database for TestDB {
-    fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
-        &self.runtime
-    }
-    fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
-        &mut self.runtime
-    }
-}
-
-impl std::panic::RefUnwindSafe for TestDB {}
-
-impl FileLoader for TestDB {
-    fn file_text(&self, file_id: FileId) -> Arc<String> {
-        FileLoaderDelegate(self).file_text(file_id)
-    }
-    fn resolve_relative_path(
-        &self,
-        anchor: FileId,
-        relative_path: &RelativePath,
-    ) -> Option<FileId> {
-        FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
-    }
-    fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
-        FileLoaderDelegate(self).relevant_crates(file_id)
-    }
-}