From b6a854e161cc122e6d9ae12084b6a1d1f4d0f241 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 30 May 2019 16:10:07 +0300
Subject: update ra_ide_api to use builtins

---
 crates/ra_ide_api/src/completion/complete_path.rs  | 20 +++++
 .../ra_ide_api/src/completion/completion_item.rs   |  2 +
 crates/ra_ide_api/src/completion/presentation.rs   |  7 +-
 crates/ra_ide_api/src/display/navigation_target.rs | 13 +++-
 crates/ra_ide_api/src/goto_definition.rs           |  5 +-
 crates/ra_ide_api/src/marks.rs                     |  1 +
 crates/ra_ide_api/src/syntax_highlighting.rs       | 88 ++++++++++------------
 7 files changed, 81 insertions(+), 55 deletions(-)

(limited to 'crates/ra_ide_api/src')

diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index c41752ae7..99da24142 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -17,6 +17,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
         hir::ModuleDef::Module(module) => {
             let module_scope = module.scope(ctx.db);
             for (name, res) in module_scope.entries() {
+                if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.as_ref().take_types() {
+                    if ctx.use_item_syntax.is_some() {
+                        tested_by!(dont_complete_primitive_in_use);
+                        continue;
+                    }
+                }
                 if Some(module) == ctx.module {
                     if let Some(import) = res.import {
                         if let Either::A(use_tree) = module.import_source(ctx.db, import) {
@@ -88,6 +94,20 @@ mod tests {
         assert_eq!(completions.len(), 2);
     }
 
+    #[test]
+    fn dont_complete_primitive_in_use() {
+        covers!(dont_complete_primitive_in_use);
+        let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType);
+        assert!(completions.is_empty());
+    }
+
+    #[test]
+    fn completes_primitives() {
+        let completions =
+            do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType);
+        assert_eq!(completions.len(), 17);
+    }
+
     #[test]
     fn completes_mod_with_docs() {
         check_reference_completion(
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 6f1392231..6f2a60640 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -78,6 +78,7 @@ pub enum CompletionItemKind {
     Keyword,
     Module,
     Function,
+    BuiltinType,
     Struct,
     Enum,
     EnumVariant,
@@ -102,6 +103,7 @@ pub(crate) enum CompletionKind {
     Magic,
     Snippet,
     Postfix,
+    BuiltinType,
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 064d379a4..d405161d6 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -57,6 +57,7 @@ impl Completions {
             }
             Some(it) => it,
         };
+        let mut completion_kind = CompletionKind::Reference;
         let (kind, docs) = match def {
             Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)),
             Resolution::Def(Function(func)) => {
@@ -70,6 +71,10 @@ impl Completions {
             Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)),
             Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)),
             Resolution::Def(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)),
+            Resolution::Def(BuiltinType(..)) => {
+                completion_kind = CompletionKind::BuiltinType;
+                (CompletionItemKind::BuiltinType, None)
+            }
             Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None),
             Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None),
             Resolution::SelfType(..) => (
@@ -77,7 +82,7 @@ impl Completions {
                 None,
             ),
         };
-        CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
+        CompletionItem::new(completion_kind, ctx.source_range(), local_name)
             .kind(kind)
             .set_documentation(docs)
             .add_to(self)
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index ae729614f..e19c071b0 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -165,8 +165,11 @@ impl NavigationTarget {
         }
     }
 
-    pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget {
-        match module_def {
+    pub(crate) fn from_def(
+        db: &RootDatabase,
+        module_def: hir::ModuleDef,
+    ) -> Option<NavigationTarget> {
+        let nav = match module_def {
             hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
             hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func),
             hir::ModuleDef::Struct(s) => {
@@ -201,7 +204,11 @@ impl NavigationTarget {
                 let (file_id, node) = e.source(db);
                 NavigationTarget::from_named(file_id.original_file(db), &*node)
             }
-        }
+            hir::ModuleDef::BuiltinType(..) => {
+                return None;
+            }
+        };
+        Some(nav)
     }
 
     pub(crate) fn from_impl_block(
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 4f8554625..97b367115 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -62,7 +62,10 @@ pub(crate) fn reference_definition(
         Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)),
         Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)),
         Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_impl_item(db, assoc)),
-        Some(Def(def)) => return Exact(NavigationTarget::from_def(db, def)),
+        Some(Def(def)) => match NavigationTarget::from_def(db, def) {
+            Some(nav) => return Exact(nav),
+            None => return Approximate(vec![]),
+        },
         Some(SelfType(ty)) => {
             if let Some((def_id, _)) = ty.as_adt() {
                 return Exact(NavigationTarget::from_adt_def(db, def_id));
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index cc894a7df..9cb991de5 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -6,4 +6,5 @@ test_utils::marks!(
     goto_definition_works_for_named_fields
     call_info_bad_offset
     dont_complete_current_use
+    dont_complete_primitive_in_use
 );
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 4b24754a8..3a04a51cd 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -30,14 +30,6 @@ fn is_control_keyword(kind: SyntaxKind) -> bool {
     }
 }
 
-fn is_prim_type(node: &ast::NameRef) -> bool {
-    match node.text().as_str() {
-        "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "usize"
-        | "isize" | "f32" | "f64" | "bool" | "char" | "str" => true,
-        _ => false,
-    }
-}
-
 pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
     let _p = profile("highlight");
     let source_file = db.parse(file_id).tree;
@@ -71,51 +63,47 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
             NAME_REF => {
                 if let Some(name_ref) = node.as_node().and_then(ast::NameRef::cast) {
                     // FIXME: revisit this after #1340
-                    if is_prim_type(name_ref) {
-                        "type"
-                    } else {
-                        use crate::name_ref_kind::{classify_name_ref, NameRefKind::*};
-                        use hir::{ModuleDef, ImplItem};
+                    use crate::name_ref_kind::{classify_name_ref, NameRefKind::*};
+                    use hir::{ModuleDef, ImplItem};
 
-                        // FIXME: try to reuse the SourceAnalyzers
-                        let analyzer =
-                            hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
-                        match classify_name_ref(db, &analyzer, name_ref) {
-                            Some(Method(_)) => "function",
-                            Some(Macro(_)) => "macro",
-                            Some(FieldAccess(_)) => "field",
-                            Some(AssocItem(ImplItem::Method(_))) => "function",
-                            Some(AssocItem(ImplItem::Const(_))) => "constant",
-                            Some(AssocItem(ImplItem::TypeAlias(_))) => "type",
-                            Some(Def(ModuleDef::Module(_))) => "module",
-                            Some(Def(ModuleDef::Function(_))) => "function",
-                            Some(Def(ModuleDef::Struct(_))) => "type",
-                            Some(Def(ModuleDef::Union(_))) => "type",
-                            Some(Def(ModuleDef::Enum(_))) => "type",
-                            Some(Def(ModuleDef::EnumVariant(_))) => "constant",
-                            Some(Def(ModuleDef::Const(_))) => "constant",
-                            Some(Def(ModuleDef::Static(_))) => "constant",
-                            Some(Def(ModuleDef::Trait(_))) => "type",
-                            Some(Def(ModuleDef::TypeAlias(_))) => "type",
-                            Some(SelfType(_)) => "type",
-                            Some(Pat(ptr)) => {
-                                binding_hash = Some({
-                                    let text = ptr
-                                        .syntax_node_ptr()
-                                        .to_node(&source_file.syntax())
-                                        .text()
-                                        .to_smol_string();
-                                    let shadow_count =
-                                        bindings_shadow_count.entry(text.clone()).or_default();
-                                    calc_binding_hash(file_id, &text, *shadow_count)
-                                });
+                    // FIXME: try to reuse the SourceAnalyzers
+                    let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
+                    match classify_name_ref(db, &analyzer, name_ref) {
+                        Some(Method(_)) => "function",
+                        Some(Macro(_)) => "macro",
+                        Some(FieldAccess(_)) => "field",
+                        Some(AssocItem(ImplItem::Method(_))) => "function",
+                        Some(AssocItem(ImplItem::Const(_))) => "constant",
+                        Some(AssocItem(ImplItem::TypeAlias(_))) => "type",
+                        Some(Def(ModuleDef::Module(_))) => "module",
+                        Some(Def(ModuleDef::Function(_))) => "function",
+                        Some(Def(ModuleDef::Struct(_))) => "type",
+                        Some(Def(ModuleDef::Union(_))) => "type",
+                        Some(Def(ModuleDef::Enum(_))) => "type",
+                        Some(Def(ModuleDef::EnumVariant(_))) => "constant",
+                        Some(Def(ModuleDef::Const(_))) => "constant",
+                        Some(Def(ModuleDef::Static(_))) => "constant",
+                        Some(Def(ModuleDef::Trait(_))) => "type",
+                        Some(Def(ModuleDef::TypeAlias(_))) => "type",
+                        Some(Def(ModuleDef::BuiltinType(_))) => "type",
+                        Some(SelfType(_)) => "type",
+                        Some(Pat(ptr)) => {
+                            binding_hash = Some({
+                                let text = ptr
+                                    .syntax_node_ptr()
+                                    .to_node(&source_file.syntax())
+                                    .text()
+                                    .to_smol_string();
+                                let shadow_count =
+                                    bindings_shadow_count.entry(text.clone()).or_default();
+                                calc_binding_hash(file_id, &text, *shadow_count)
+                            });
 
-                                "variable"
-                            }
-                            Some(SelfParam(_)) => "type",
-                            Some(GenericParam(_)) => "type",
-                            None => "text",
+                            "variable"
                         }
+                        Some(SelfParam(_)) => "type",
+                        Some(GenericParam(_)) => "type",
+                        None => "text",
                     }
                 } else {
                     "text"
-- 
cgit v1.2.3