about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-05-13 12:26:45 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-05-13 12:26:45 +0200
commita73973934f86a1e0c68d32752bb48123e92a4c63 (patch)
tree8bf9ea682af331266d6323b527334c527c6454f7
parent6a3556b779f15c35b7a0e3a3631501c7d9b9e154 (diff)
downloadrust-a73973934f86a1e0c68d32752bb48123e92a4c63.tar.gz
rust-a73973934f86a1e0c68d32752bb48123e92a4c63.zip
Fix literal hovers being confusing and wrong for floats
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs57
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs56
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs141
4 files changed, 171 insertions, 97 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 149e75c45cb..275c1390f27 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -2543,6 +2543,20 @@ impl BuiltinType {
         matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
     }
 
+    pub fn is_f32(&self) -> bool {
+        matches!(
+            self.inner,
+            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
+        )
+    }
+
+    pub fn is_f64(&self) -> bool {
+        matches!(
+            self.inner,
+            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
+        )
+    }
+
     pub fn is_char(&self) -> bool {
         matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index f9210da5fd4..6b73afe08ea 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -298,61 +298,8 @@ fn hover_simple(
         })
         // tokens
         .or_else(|| {
-            let mut res = HoverResult::default();
-            match_ast! {
-                match original_token {
-                    ast::String(string) => {
-                        res.markup = Markup::fenced_block_text(format_args!("{}", string.value()?));
-                    },
-                    ast::ByteString(string) => {
-                        res.markup = Markup::fenced_block_text(format_args!("{:?}", string.value()?));
-                    },
-                    ast::CString(string) => {
-                        let val = string.value()?;
-                        res.markup = Markup::fenced_block_text(format_args!("{}", std::str::from_utf8(val.as_ref()).ok()?));
-                    },
-                    ast::Char(char) => {
-                        let mut res = HoverResult::default();
-                        res.markup = Markup::fenced_block_text(format_args!("{}", char.value()?));
-                    },
-                    ast::Byte(byte) => {
-                        res.markup = Markup::fenced_block_text(format_args!("0x{:X}", byte.value()?));
-                    },
-                    ast::FloatNumber(num) => {
-                        res.markup = if num.suffix() == Some("f32") {
-                            match num.value_f32() {
-                                Ok(num) => {
-                                    Markup::fenced_block_text(format_args!("{num} (bits: 0x{:X})", num.to_bits()))
-                                },
-                                Err(e) => {
-                                    Markup::fenced_block_text(format_args!("{e}"))
-                                },
-                            }
-                        } else {
-                            match num.value() {
-                                Ok(num) => {
-                                    Markup::fenced_block_text(format_args!("{num} (bits: 0x{:X})", num.to_bits()))
-                                },
-                                Err(e) => {
-                                    Markup::fenced_block_text(format_args!("{e}"))
-                                },
-                            }
-                        };
-                    },
-                    ast::IntNumber(num) => {
-                        res.markup = match num.value() {
-                            Ok(num) => {
-                                Markup::fenced_block_text(format_args!("{num} (0x{num:X}|0b{num:b})"))
-                            },
-                            Err(e) => {
-                                Markup::fenced_block_text(format_args!("{e}"))
-                            },
-                        };
-                    },
-                    _ => return None
-                }
-            }
-            Some(res)
+            render::literal(sema, original_token.clone())
+                .map(|markup| HoverResult { markup, actions: vec![] })
         });
 
     result.map(|mut res: HoverResult| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index ee96767411a..674b32a7f5c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -17,11 +17,7 @@ use ide_db::{
 };
 use itertools::Itertools;
 use stdx::format_to;
-use syntax::{
-    algo,
-    ast::{self, RecordPat},
-    match_ast, AstNode, Direction, SyntaxToken, T,
-};
+use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T};
 
 use crate::{
     doc_links::{remove_links, rewrite_links},
@@ -276,7 +272,7 @@ pub(super) fn keyword(
 pub(super) fn struct_rest_pat(
     sema: &Semantics<'_, RootDatabase>,
     _config: &HoverConfig,
-    pattern: &RecordPat,
+    pattern: &ast::RecordPat,
 ) -> HoverResult {
     let missing_fields = sema.record_pattern_missing_fields(pattern);
 
@@ -526,6 +522,54 @@ pub(super) fn definition(
     markup(docs.map(Into::into), desc, mod_path)
 }
 
+pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Markup> {
+    let lit = token.parent().and_then(ast::Literal::cast)?;
+    let ty = if let Some(p) = lit.syntax().parent().and_then(ast::Pat::cast) {
+        sema.type_of_pat(&p)?
+    } else {
+        sema.type_of_expr(&ast::Expr::Literal(lit))?
+    }
+    .original;
+
+    let value = match_ast! {
+        match token {
+            ast::String(string) => Ok(string.value()?.to_string()),
+            ast::ByteString(string) => Ok(format_args!("{:?}", string.value()?).to_string()),
+            ast::CString(string) => Ok(std::str::from_utf8(string.value()?.as_ref()).ok()?.to_owned()),
+            ast::Char(char) => Ok(char.value()?.to_string()),
+            ast::Byte(byte) => Ok(format!("0x{:X}", byte.value()?)),
+            ast::FloatNumber(num) => {
+                let (text, _) = num.split_into_parts();
+                let text = text.replace('_', "");
+                if ty.as_builtin().map(|it| it.is_f32()).unwrap_or(false) {
+                    match text.parse::<f32>() {
+                        Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
+                        Err(e) => Err(e.to_string()),
+                    }
+                } else {
+                    match text.parse::<f64>() {
+                        Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
+                        Err(e) => Err(e.to_string()),
+                    }
+                }
+            },
+            ast::IntNumber(num) => match num.value() {
+                Ok(num) => Ok(format!("{num} (0x{num:X}|0b{num:b})")),
+                Err(e) => Err(e.to_string()),
+            },
+            _ => return None
+        }
+    };
+    let ty = ty.display(sema.db);
+
+    let mut s = format!("```rust\n{ty}\n```\n___\n\n");
+    match value {
+        Ok(value) => format_to!(s, "value of literal: {value}"),
+        Err(error) => format_to!(s, "invalid literal: {error}"),
+    }
+    Some(s.into())
+}
+
 fn render_notable_trait_comment(
     db: &RootDatabase,
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index f7af7950041..b5547c05148 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -7790,9 +7790,12 @@ fn main() {
 "#,
         expect![[r#"
             *"🦀\u{1f980}\\\x41"*
-            ```text
-            🦀🦀\A
+            ```rust
+            &str
             ```
+            ___
+
+            value of literal: 🦀🦀\A
         "#]],
     );
     check(
@@ -7803,9 +7806,12 @@ fn main() {
 "#,
         expect![[r#"
             *r"🦀\u{1f980}\\\x41"*
-            ```text
-            🦀\u{1f980}\\\x41
+            ```rust
+            &str
             ```
+            ___
+
+            value of literal: 🦀\u{1f980}\\\x41
         "#]],
     );
 }
@@ -7820,9 +7826,12 @@ fn main() {
 "#,
         expect![[r#"
             *c"🦀\u{1f980}\\\x41"*
-            ```text
-            🦀🦀\A
+            ```rust
+            &{unknown}
             ```
+            ___
+
+            value of literal: 🦀🦀\A
         "#]],
     );
 }
@@ -7837,9 +7846,12 @@ fn main() {
 "#,
         expect![[r#"
             *b"\xF0\x9F\xA6\x80\\"*
-            ```text
-            [240, 159, 166, 128, 92]
+            ```rust
+            &[u8; 5]
             ```
+            ___
+
+            value of literal: [240, 159, 166, 128, 92]
         "#]],
     );
     check(
@@ -7850,9 +7862,12 @@ fn main() {
 "#,
         expect![[r#"
             *br"\xF0\x9F\xA6\x80\\"*
-            ```text
-            [92, 120, 70, 48, 92, 120, 57, 70, 92, 120, 65, 54, 92, 120, 56, 48, 92, 92]
+            ```rust
+            &[u8; 18]
             ```
+            ___
+
+            value of literal: [92, 120, 70, 48, 92, 120, 57, 70, 92, 120, 65, 54, 92, 120, 56, 48, 92, 92]
         "#]],
     );
 }
@@ -7867,9 +7882,12 @@ fn main() {
 "#,
         expect![[r#"
             *b'\xF0'*
-            ```text
-            0xF0
+            ```rust
+            u8
             ```
+            ___
+
+            value of literal: 0xF0
         "#]],
     );
     check(
@@ -7880,9 +7898,12 @@ fn main() {
 "#,
         expect![[r#"
             *b'\\'*
-            ```text
-            0x5C
+            ```rust
+            u8
             ```
+            ___
+
+            value of literal: 0x5C
         "#]],
     );
 }
@@ -7897,7 +7918,12 @@ fn main() {
 "#,
         expect![[r#"
             *'\x41'*
+            ```rust
+            char
+            ```
+            ___
 
+            value of literal: A
         "#]],
     );
     check(
@@ -7908,7 +7934,12 @@ fn main() {
 "#,
         expect![[r#"
             *'\\'*
+            ```rust
+            char
+            ```
+            ___
 
+            value of literal: \
         "#]],
     );
     check(
@@ -7919,7 +7950,12 @@ fn main() {
 "#,
         expect![[r#"
             *'\u{1f980}'*
+            ```rust
+            char
+            ```
+            ___
 
+            value of literal: 🦀
         "#]],
     );
 }
@@ -7934,9 +7970,12 @@ fn main() {
 "#,
         expect![[r#"
             *1.0*
-            ```text
-            1 (bits: 0x3FF0000000000000)
+            ```rust
+            f64
             ```
+            ___
+
+            value of literal: 1 (bits: 0x3FF0000000000000)
         "#]],
     );
     check(
@@ -7947,9 +7986,12 @@ fn main() {
 "#,
         expect![[r#"
             *1.0f32*
-            ```text
-            1 (bits: 0x3F800000)
+            ```rust
+            f32
             ```
+            ___
+
+            value of literal: 1 (bits: 0x3F800000)
         "#]],
     );
     check(
@@ -7960,9 +8002,12 @@ fn main() {
 "#,
         expect![[r#"
             *134e12*
-            ```text
-            134000000000000 (bits: 0x42DE77D399980000)
+            ```rust
+            f64
             ```
+            ___
+
+            value of literal: 134000000000000 (bits: 0x42DE77D399980000)
         "#]],
     );
     check(
@@ -7973,9 +8018,12 @@ fn main() {
 "#,
         expect![[r#"
             *1523527134274733643531312.0*
-            ```text
-            1523527134274733600000000 (bits: 0x44F429E9249F629B)
+            ```rust
+            f64
             ```
+            ___
+
+            value of literal: 1523527134274733600000000 (bits: 0x44F429E9249F629B)
         "#]],
     );
     check(
@@ -7986,9 +8034,12 @@ fn main() {
 "#,
         expect![[r#"
             *0.1ea123*
-            ```text
-            invalid float literal
+            ```rust
+            f64
             ```
+            ___
+
+            invalid literal: invalid float literal
         "#]],
     );
 }
@@ -8003,9 +8054,12 @@ fn main() {
 "#,
         expect![[r#"
             *34325236457856836345234*
-            ```text
-            34325236457856836345234 (0x744C659178614489D92|0b111010001001100011001011001000101111000011000010100010010001001110110010010)
+            ```rust
+            i32
             ```
+            ___
+
+            value of literal: 34325236457856836345234 (0x744C659178614489D92|0b111010001001100011001011001000101111000011000010100010010001001110110010010)
         "#]],
     );
     check(
@@ -8016,9 +8070,12 @@ fn main() {
 "#,
         expect![[r#"
             *134_123424_21*
-            ```text
-            13412342421 (0x31F701A95|0b1100011111011100000001101010010101)
+            ```rust
+            i32
             ```
+            ___
+
+            value of literal: 13412342421 (0x31F701A95|0b1100011111011100000001101010010101)
         "#]],
     );
     check(
@@ -8029,9 +8086,12 @@ fn main() {
 "#,
         expect![[r#"
             *0x12423423*
-            ```text
-            306328611 (0x12423423|0b10010010000100011010000100011)
+            ```rust
+            i32
             ```
+            ___
+
+            value of literal: 306328611 (0x12423423|0b10010010000100011010000100011)
         "#]],
     );
     check(
@@ -8042,9 +8102,12 @@ fn main() {
 "#,
         expect![[r#"
             *0b1111_1111*
-            ```text
-            255 (0xFF|0b11111111)
+            ```rust
+            i32
             ```
+            ___
+
+            value of literal: 255 (0xFF|0b11111111)
         "#]],
     );
     check(
@@ -8055,9 +8118,12 @@ fn main() {
 "#,
         expect![[r#"
             *0o12345*
-            ```text
-            5349 (0x14E5|0b1010011100101)
+            ```rust
+            i32
             ```
+            ___
+
+            value of literal: 5349 (0x14E5|0b1010011100101)
         "#]],
     );
     check(
@@ -8068,9 +8134,12 @@ fn main() {
 "#,
         expect![[r#"
             *0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_F*
-            ```text
-            number too large to fit in target type
+            ```rust
+            i32
             ```
+            ___
+
+            invalid literal: number too large to fit in target type
         "#]],
     );
 }