]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide/src/hover.rs
Merge #11461
[rust.git] / crates / ide / src / hover.rs
index 9d19d7c1c015e35fb4c6a14fd2733a0ced74c1c6..0eba0b09ba6e2dfded2f179b785f18c7e1bcd5a0 100644 (file)
@@ -9,7 +9,7 @@
 use hir::{HasSource, Semantics};
 use ide_db::{
     base_db::FileRange,
-    defs::Definition,
+    defs::{Definition, IdentClass},
     helpers::{pick_best_token, FamousDefs},
     FxIndexSet, RootDatabase,
 };
@@ -94,11 +94,10 @@ pub(crate) fn hover(
     let sema = &hir::Semantics::new(db);
     let file = sema.parse(file_id).syntax().clone();
 
-    let offset = if !range.is_empty() {
+    if !range.is_empty() {
         return hover_ranged(&file, range, sema, config);
-    } else {
-        range.start()
-    };
+    }
+    let offset = range.start();
 
     let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
         IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3,
@@ -118,10 +117,11 @@ pub(crate) fn hover(
     let descended = sema.descend_into_macros(original_token.clone());
 
     // FIXME: Definition should include known lints and the like instead of having this special case here
-    if let Some(res) = descended.iter().find_map(|token| {
+    let hovered_lint = descended.iter().find_map(|token| {
         let attr = token.ancestors().find_map(ast::Attr::cast)?;
         render::try_for_lint(&attr, token)
-    }) {
+    });
+    if let Some(res) = hovered_lint {
         return Some(RangeInfo::new(original_token.text_range(), res));
     }
 
@@ -129,8 +129,8 @@ pub(crate) fn hover(
         .iter()
         .filter_map(|token| {
             let node = token.parent()?;
-            let defs = Definition::from_token(sema, token);
-            Some(defs.into_iter().zip(iter::once(node).cycle()))
+            let class = IdentClass::classify_token(sema, token)?;
+            Some(class.definitions().into_iter().zip(iter::once(node).cycle()))
         })
         .flatten()
         .unique_by(|&(def, _)| def)
@@ -143,12 +143,15 @@ pub(crate) fn hover(
 
     if result.is_none() {
         // fallbacks, show keywords or types
-        if let Some(res) = render::keyword(sema, config, &original_token) {
+
+        let res = descended.iter().find_map(|token| render::keyword(sema, config, &token));
+        if let Some(res) = res {
             return Some(RangeInfo::new(original_token.text_range(), res));
         }
-        if let res @ Some(_) =
-            descended.iter().find_map(|token| hover_type_fallback(sema, config, token))
-        {
+        let res = descended
+            .iter()
+            .find_map(|token| hover_type_fallback(sema, config, token, &original_token));
+        if let res @ Some(_) = res {
             return res;
         }
     }
@@ -198,6 +201,7 @@ fn hover_ranged(
     sema: &Semantics<RootDatabase>,
     config: &HoverConfig,
 ) -> Option<RangeInfo<HoverResult>> {
+    // FIXME: make this work in attributes
     let expr_or_pat = file.covering_element(range).ancestors().find_map(|it| {
         match_ast! {
             match it {
@@ -230,6 +234,7 @@ fn hover_type_fallback(
     sema: &Semantics<RootDatabase>,
     config: &HoverConfig,
     token: &SyntaxToken,
+    original_token: &SyntaxToken,
 ) -> Option<RangeInfo<HoverResult>> {
     let node = token
         .ancestors()
@@ -248,7 +253,10 @@ fn hover_type_fallback(
     };
 
     let res = render::type_info(sema, config, &expr_or_pat)?;
-    let range = sema.original_range(&node).range;
+    let range = sema
+        .original_range_opt(&node)
+        .map(|frange| frange.range)
+        .unwrap_or_else(|| original_token.text_range());
     Some(RangeInfo::new(range, res))
 }