]> git.lizzy.rs Git - rust.git/commitdiff
Add imports in auto completion
authorKirill Bulatov <mail4score@gmail.com>
Fri, 18 Sep 2020 20:40:11 +0000 (23:40 +0300)
committerKirill Bulatov <mail4score@gmail.com>
Mon, 16 Nov 2020 19:19:05 +0000 (21:19 +0200)
14 files changed:
Cargo.lock
crates/assists/src/handlers/auto_import.rs
crates/assists/src/handlers/extract_struct_from_enum_variant.rs
crates/assists/src/handlers/replace_qualified_name_with_use.rs
crates/assists/src/utils.rs
crates/assists/src/utils/insert_use.rs
crates/completion/Cargo.toml
crates/completion/src/completions.rs
crates/completion/src/completions/complete_magic.rs [new file with mode: 0644]
crates/completion/src/item.rs
crates/completion/src/lib.rs
crates/hir/src/code_model.rs
crates/hir/src/lib.rs
crates/ide_db/src/imports_locator.rs

index 715a809789c70f527213d227d0cc5117572ede52..eb4e43ad951f95e71453051f215862d806f098f9 100644 (file)
@@ -2,9 +2,9 @@
 # It is not intended for manual editing.
 [[package]]
 name = "addr2line"
-version = "0.14.0"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
+checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
 dependencies = [
  "gimli",
 ]
@@ -26,9 +26,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.34"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
+checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
 
 [[package]]
 name = "anymap"
@@ -42,9 +42,9 @@ version = "0.0.0"
 
 [[package]]
 name = "arrayvec"
-version = "0.5.2"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
 
 [[package]]
 name = "assists"
@@ -81,9 +81,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 [[package]]
 name = "backtrace"
-version = "0.3.54"
+version = "0.3.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28"
+checksum = "707b586e0e2f247cbde68cdd2c3ce69ea7b7be43e1c5b426e37c9319c4b9838e"
 dependencies = [
  "addr2line",
  "cfg-if 1.0.0",
@@ -132,7 +132,7 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345"
 dependencies = [
- "semver 0.11.0",
+ "semver",
  "serde",
  "serde_json",
 ]
@@ -255,6 +255,7 @@ version = "0.0.0"
 dependencies = [
  "assists",
  "base_db",
+ "either",
  "expect-test",
  "hir",
  "ide_db",
@@ -270,17 +271,17 @@ dependencies = [
 
 [[package]]
 name = "const_fn"
-version = "0.4.3"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
+checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2"
 
 [[package]]
 name = "crc32fast"
-version = "1.2.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
 ]
 
 [[package]]
@@ -417,11 +418,11 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
 
 [[package]]
 name = "flate2"
-version = "1.0.19"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
+checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
  "crc32fast",
  "libc",
  "miniz_oxide",
@@ -470,9 +471,9 @@ dependencies = [
 
 [[package]]
 name = "fst"
-version = "0.4.5"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f"
+checksum = "a7293de202dbfe786c0b3fe6110a027836c5438ed06db7b715c9955ff4bfea51"
 
 [[package]]
 name = "fuchsia-zircon"
@@ -490,24 +491,11 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 
-[[package]]
-name = "generator"
-version = "0.6.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cdc09201b2e8ca1b19290cf7e65de2246b8e91fb6874279722189c4de7b94dc"
-dependencies = [
- "cc",
- "libc",
- "log",
- "rustc_version",
- "winapi 0.3.9",
-]
-
 [[package]]
 name = "gimli"
-version = "0.23.0"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
+checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
 
 [[package]]
 name = "goblin"
@@ -735,11 +723,11 @@ dependencies = [
 
 [[package]]
 name = "instant"
-version = "0.1.8"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613"
+checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
 ]
 
 [[package]]
@@ -796,17 +784,17 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.80"
+version = "0.2.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
 
 [[package]]
 name = "libloading"
-version = "0.6.5"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0"
+checksum = "3557c9384f7f757f6d139cd3a4c62ef4e850696c16bf27924a5538c8a09717a1"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
  "winapi 0.3.9",
 ]
 
@@ -837,19 +825,6 @@ dependencies = [
  "cfg-if 0.1.10",
 ]
 
-[[package]]
-name = "loom"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed"
-dependencies = [
- "cfg-if 0.1.10",
- "generator",
- "scoped-tls",
- "serde",
- "serde_json",
-]
-
 [[package]]
 name = "lsp-server"
 version = "0.4.1"
@@ -912,9 +887,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.3.4"
+version = "2.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
 
 [[package]]
 name = "memmap"
@@ -1010,9 +985,9 @@ dependencies = [
 
 [[package]]
 name = "notify"
-version = "5.0.0-pre.4"
+version = "5.0.0-pre.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8b946889dfdad884379cd56367d93b6d0ce8889cc027d26a69a3a31c0a03bb5"
+checksum = "77d03607cf88b4b160ba0e9ed425fff3cee3b55ac813f0c685b3a3772da37d0e"
 dependencies = [
  "anymap",
  "bitflags",
@@ -1030,9 +1005,9 @@ dependencies = [
 
 [[package]]
 name = "num-integer"
-version = "0.1.44"
+version = "0.1.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
 dependencies = [
  "autocfg",
  "num-traits",
@@ -1040,9 +1015,9 @@ dependencies = [
 
 [[package]]
 name = "num-traits"
-version = "0.2.14"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
 dependencies = [
  "autocfg",
 ]
@@ -1059,9 +1034,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.22.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
+checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693"
 
 [[package]]
 name = "once_cell"
@@ -1310,9 +1285,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
 
 [[package]]
 name = "regex"
-version = "1.4.2"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
+checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
 dependencies = [
  "regex-syntax",
 ]
@@ -1329,9 +1304,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.21"
+version = "0.6.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
+checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
 
 [[package]]
 name = "rowan"
@@ -1404,9 +1379,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.18"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
+checksum = "b2610b7f643d18c87dff3b489950269617e6601a51f1f05aa5daefee36f64f0b"
 
 [[package]]
 name = "rustc-hash"
@@ -1414,15 +1389,6 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver 0.9.0",
-]
-
 [[package]]
 name = "ryu"
 version = "1.0.5"
@@ -1490,40 +1456,25 @@ dependencies = [
 
 [[package]]
 name = "scroll_derive"
-version = "0.10.4"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d"
+checksum = "6dfde5d1531034db129e95c76ac857e2baecea3443579d493d02224950b0fb6d"
 dependencies = [
  "proc-macro2",
  "quote",
  "syn",
 ]
 
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser 0.7.0",
-]
-
 [[package]]
 name = "semver"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
 dependencies = [
- "semver-parser 0.10.1",
+ "semver-parser",
  "serde",
 ]
 
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
 [[package]]
 name = "semver-parser"
 version = "0.10.1"
@@ -1577,12 +1528,11 @@ dependencies = [
 
 [[package]]
 name = "sharded-slab"
-version = "0.1.0"
+version = "0.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4921be914e16899a80adefb821f8ddb7974e3f1250223575a44ed994882127"
+checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e"
 dependencies = [
  "lazy_static",
- "loom",
 ]
 
 [[package]]
@@ -1626,9 +1576,9 @@ version = "0.0.0"
 
 [[package]]
 name = "syn"
-version = "1.0.48"
+version = "1.0.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
+checksum = "ea9c5432ff16d6152371f808fb5a871cd67368171b09bb21b43df8e4a47a3556"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1805,9 +1755,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.2.15"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401"
+checksum = "4ef0a5e15477aa303afbfac3a44cba9b6430fdaad52423b1e6c0dbbe28c3eedd"
 dependencies = [
  "ansi_term",
  "chrono",
index 37dd6126618efd813d9bd592246b795481618214..d665837a2f3bad0b4b8279ca1ca16f2cfdac8fda 100644 (file)
@@ -98,7 +98,8 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
 
     let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range;
     let group = import_group_message(import_assets.import_candidate());
-    let scope = ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), ctx)?;
+    let scope =
+        ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), &ctx.sema)?;
     for (import, _) in proposed_imports {
         acc.add_group(
             &group,
index 067afabf2edf7b45c765ac40c32d82e693ad10e0..cac77c49bbc46fdc601245e4881f945e1689e1ea 100644 (file)
@@ -143,8 +143,7 @@ fn insert_import(
     if let Some(mut mod_path) = mod_path {
         mod_path.segments.pop();
         mod_path.segments.push(variant_hir_name.clone());
-        let scope = ImportScope::find_insert_use_container(scope_node, ctx)?;
-
+        let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?;
         *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge);
     }
     Some(())
index d7e1d95805e67529b4f172bd19b0bec2c5c1a55e..a66db9ae3a15f271b78fc8a9a7e58edda1b1ae9e 100644 (file)
@@ -34,7 +34,7 @@ pub(crate) fn replace_qualified_name_with_use(
     }
 
     let target = path.syntax().text_range();
-    let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
+    let scope = ImportScope::find_insert_use_container(path.syntax(), &ctx.sema)?;
     let syntax = scope.as_syntax_node();
     acc.add(
         AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
index 7bd338e99c750e2a548c22dfadbda13c542a807e..caabc44dea50216add89af6a6ce0292e4964b4b4 100644 (file)
@@ -21,8 +21,7 @@
     ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
 };
 
-pub use insert_use::MergeBehaviour;
-pub(crate) use insert_use::{insert_use, ImportScope};
+pub use insert_use::{insert_use, ImportScope, MergeBehaviour};
 
 pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
     let mut segments = Vec::new();
index af3fc96b6c2fce2b4e89bb624b9e85092256b17f..1aa727e11fe5de95c9a3e9fdc90a9846727e38ca 100644 (file)
@@ -1,6 +1,8 @@
 //! Handle syntactic aspects of inserting a new `use`.
 use std::{cmp::Ordering, iter::successors};
 
+use hir::Semantics;
+use ide_db::RootDatabase;
 use itertools::{EitherOrBoth, Itertools};
 use syntax::{
     algo::SyntaxRewriter,
@@ -14,7 +16,7 @@
 use test_utils::mark;
 
 #[derive(Debug)]
-pub(crate) enum ImportScope {
+pub enum ImportScope {
     File(ast::SourceFile),
     Module(ast::ItemList),
 }
@@ -31,14 +33,14 @@ pub(crate) fn from(syntax: SyntaxNode) -> Option<Self> {
     }
 
     /// Determines the containing syntax node in which to insert a `use` statement affecting `position`.
-    pub(crate) fn find_insert_use_container(
+    pub fn find_insert_use_container(
         position: &SyntaxNode,
-        ctx: &crate::assist_context::AssistContext,
+        sema: &Semantics<'_, RootDatabase>,
     ) -> Option<Self> {
-        ctx.sema.ancestors_with_macros(position.clone()).find_map(Self::from)
+        sema.ancestors_with_macros(position.clone()).find_map(Self::from)
     }
 
-    pub(crate) fn as_syntax_node(&self) -> &SyntaxNode {
+    pub fn as_syntax_node(&self) -> &SyntaxNode {
         match self {
             ImportScope::File(file) => file.syntax(),
             ImportScope::Module(item_list) => item_list.syntax(),
@@ -88,7 +90,7 @@ fn is_inner_comment(token: SyntaxToken) -> bool {
 }
 
 /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
-pub(crate) fn insert_use<'a>(
+pub fn insert_use<'a>(
     scope: &ImportScope,
     path: ast::Path,
     merge: Option<MergeBehaviour>,
index 3015ec9e0ea4e49bf149c555cd55989fdb77a911..799b4a3d54453aeb1b11017adf2233e70d8bb55b 100644 (file)
@@ -13,6 +13,7 @@ doctest = false
 itertools = "0.9.0"
 log = "0.4.8"
 rustc-hash = "1.1.0"
+either = "1.6.1"
 
 assists = { path = "../assists", version = "0.0.0" }
 stdx = { path = "../stdx", version = "0.0.0" }
@@ -21,6 +22,7 @@ text_edit = { path = "../text_edit", version = "0.0.0" }
 base_db = { path = "../base_db", version = "0.0.0" }
 ide_db = { path = "../ide_db", version = "0.0.0" }
 profile = { path = "../profile", version = "0.0.0" }
+assists = { path = "../assists", version = "0.0.0" }
 test_utils = { path = "../test_utils", version = "0.0.0" }
 
 # completions crate should depend only on the top-level `hir` package. if you need
index 75dbb1a23bb5c8c616d7c2b752994aa573e627e9..99db5f9980f3bd2d032a3f2cdd51200efef236e5 100644 (file)
@@ -13,6 +13,7 @@
 pub(crate) mod macro_in_item_position;
 pub(crate) mod trait_impl;
 pub(crate) mod mod_;
+pub(crate) mod complete_magic;
 
 use hir::{ModPath, ScopeDef, Type};
 
diff --git a/crates/completion/src/completions/complete_magic.rs b/crates/completion/src/completions/complete_magic.rs
new file mode 100644 (file)
index 0000000..857a0b6
--- /dev/null
@@ -0,0 +1,114 @@
+//! TODO kb move this into the complete_unqualified_path when starts to work properly
+
+use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
+use hir::Query;
+use itertools::Itertools;
+use syntax::AstNode;
+use text_edit::TextEdit;
+
+use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind};
+
+use super::Completions;
+
+pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
+    if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
+        return None;
+    }
+    let current_module = ctx.scope.module()?;
+    let anchor = ctx.name_ref_syntax.as_ref()?;
+    let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
+    // TODO kb now this is the whole file, which is not disjoint with any other change in the same file, fix it
+    // otherwise it's impossible to correctly add the use statement and also change the completed text into something more meaningful
+    let import_syntax = import_scope.as_syntax_node();
+
+    // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion"
+    // TODO kb module functions are not completed, consider `std::io::stdin` one
+    let potential_import_name = ctx.token.to_string();
+
+    let possible_imports = ctx
+        .krate?
+        // TODO kb use imports_locator instead?
+        .query_external_importables(ctx.db, Query::new(&potential_import_name).limit(40))
+        .unique()
+        .filter_map(|import_candidate| match import_candidate {
+            either::Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def),
+            either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def),
+        })
+        .filter_map(|mod_path| {
+            let correct_qualifier = mod_path.segments.last()?.to_string();
+            let rewriter =
+                insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full));
+            let rewritten_node = rewriter.rewrite(import_syntax);
+            let insert_use_edit =
+                TextEdit::replace(import_syntax.text_range(), rewritten_node.to_string());
+            let mut completion_edit =
+                TextEdit::replace(anchor.syntax().text_range(), correct_qualifier);
+            completion_edit.union(insert_use_edit).expect("TODO kb");
+
+            let completion_item: CompletionItem = CompletionItem::new(
+                CompletionKind::Magic,
+                ctx.source_range(),
+                mod_path.to_string(),
+            )
+            .kind(CompletionItemKind::Struct)
+            .text_edit(completion_edit)
+            .into();
+            Some(completion_item)
+        });
+    acc.add_all(possible_imports);
+
+    Some(())
+}
+
+#[cfg(test)]
+mod tests {
+    use expect_test::{expect, Expect};
+
+    use crate::{
+        item::CompletionKind,
+        test_utils::{check_edit, completion_list},
+    };
+
+    fn check(ra_fixture: &str, expect: Expect) {
+        let actual = completion_list(ra_fixture, CompletionKind::Magic);
+        expect.assert_eq(&actual)
+    }
+
+    #[test]
+    fn case_insensitive_magic_completion_works() {
+        check(
+            r#"
+//- /lib.rs crate:dep
+pub struct TestStruct;
+
+//- /main.rs crate:main deps:dep
+fn main() {
+    teru<|>
+}
+"#,
+            expect![[r#"
+                st dep::TestStruct
+            "#]],
+        );
+
+        check_edit(
+            "dep::TestStruct",
+            r#"
+//- /lib.rs crate:dep
+pub struct TestStruct;
+
+//- /main.rs crate:main deps:dep
+fn main() {
+    teru<|>
+}
+"#,
+            r#"
+use dep::TestStruct;
+
+fn main() {
+    TestStruct
+}
+"#,
+        );
+    }
+}
index 6d1d085f4bc779e63ebfe1750b11577ac18494c3..f23913935c0e018e7d3287422c6efedd02a70512 100644 (file)
@@ -31,6 +31,7 @@ pub struct CompletionItem {
     ///
     /// Typically, replaces `source_range` with new identifier.
     text_edit: TextEdit,
+
     insert_text_format: InsertTextFormat,
 
     /// What item (struct, function, etc) are we completing.
index cb6e0554e9a7cededcf6cb4faf49451681b81c62..e920fa6b59d81886f3771a4aac9a26a8753ae9b0 100644 (file)
@@ -118,6 +118,7 @@ pub fn completions(
     completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
     completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
     completions::mod_::complete_mod(&mut acc, &ctx);
+    completions::complete_magic::complete_magic(&mut acc, &ctx);
 
     Some(acc)
 }
index 30a5e45809b9a2bbfa5b315e482fb3a0433aa196..37ed092ad0ad43ed6c70acfc914be095a91fb89d 100644 (file)
@@ -110,15 +110,9 @@ pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
     pub fn query_external_importables(
         self,
         db: &dyn DefDatabase,
-        query: &str,
+        query: import_map::Query,
     ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
-        import_map::search_dependencies(
-            db,
-            self.into(),
-            import_map::Query::new(query).anchor_end().case_sensitive().limit(40),
-        )
-        .into_iter()
-        .map(|item| match item {
+        import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item {
             ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
             ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
         })
index 0d184379f10242ded3695acebcf1f8dc52d39119..ad58a7cfe0755810144ece6c14d158cb29ecdf05 100644 (file)
@@ -49,6 +49,7 @@
     builtin_type::BuiltinType,
     docs::Documentation,
     find_path::PrefixKind,
+    import_map::Query,
     item_scope::ItemInNs,
     nameres::ModuleSource,
     path::{ModPath, PathKind},
index df74be00bb20861a4e7039825cf240c3071cacbd..e4f4b54274fb51eb468be4b1ace3a48b9d33a24d 100644 (file)
@@ -1,12 +1,12 @@
 //! This module contains an import search funcionality that is provided to the assists module.
 //! Later, this should be moved away to a separate crate that is accessible from the assists module.
 
-use hir::{Crate, MacroDef, ModuleDef, Semantics};
+use hir::{Crate, MacroDef, ModuleDef, Query as ImportMapQuery, Semantics};
 use syntax::{ast, AstNode, SyntaxKind::NAME};
 
 use crate::{
     defs::{Definition, NameClass},
-    symbol_index::{self, FileSymbol, Query},
+    symbol_index::{self, FileSymbol, Query as SymbolQuery},
     RootDatabase,
 };
 use either::Either;
@@ -21,12 +21,16 @@ pub fn find_imports<'a>(
     let db = sema.db;
 
     // Query dependencies first.
-    let mut candidates: FxHashSet<_> =
-        krate.query_external_importables(db, name_to_import).collect();
+    let mut candidates: FxHashSet<_> = krate
+        .query_external_importables(
+            db,
+            ImportMapQuery::new(name_to_import).anchor_end().case_sensitive().limit(40),
+        )
+        .collect();
 
     // Query the local crate using the symbol index.
     let local_results = {
-        let mut query = Query::new(name_to_import.to_string());
+        let mut query = SymbolQuery::new(name_to_import.to_string());
         query.exact();
         query.limit(40);
         symbol_index::crate_symbols(db, krate.into(), query)