diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/completion/src/completions/qualified_path.rs | 3 | ||||
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 6 | ||||
-rw-r--r-- | crates/completion/src/item.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 5 | ||||
-rw-r--r-- | crates/stdx/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/stdx/src/macros.rs | 52 | ||||
-rw-r--r-- | crates/syntax/src/display.rs | 2 |
7 files changed, 67 insertions, 7 deletions
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs index fa9e6e810..33df26761 100644 --- a/crates/completion/src/completions/qualified_path.rs +++ b/crates/completion/src/completions/qualified_path.rs | |||
@@ -590,8 +590,7 @@ fn main() { let _ = crate::$0 } | |||
590 | "#, | 590 | "#, |
591 | expect![[r##" | 591 | expect![[r##" |
592 | fn main() fn main() | 592 | fn main() fn main() |
593 | ma foo!(…) #[macro_export] | 593 | ma foo!(…) #[macro_export] macro_rules! foo |
594 | macro_rules! foo | ||
595 | "##]], | 594 | "##]], |
596 | ); | 595 | ); |
597 | } | 596 | } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 7ba99447d..53e1391f3 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -540,8 +540,7 @@ mod macros { | |||
540 | "#, | 540 | "#, |
541 | expect![[r##" | 541 | expect![[r##" |
542 | fn f() fn f() | 542 | fn f() fn f() |
543 | ma concat!(…) #[macro_export] | 543 | ma concat!(…) #[macro_export] macro_rules! concat |
544 | macro_rules! concat | ||
545 | md std | 544 | md std |
546 | "##]], | 545 | "##]], |
547 | ); | 546 | ); |
@@ -597,8 +596,7 @@ fn main() { let v = $0 } | |||
597 | "#, | 596 | "#, |
598 | expect![[r##" | 597 | expect![[r##" |
599 | md m1 | 598 | md m1 |
600 | ma baz!(…) #[macro_export] | 599 | ma baz!(…) #[macro_export] macro_rules! baz |
601 | macro_rules! baz | ||
602 | fn main() fn main() | 600 | fn main() fn main() |
603 | md m2 | 601 | md m2 |
604 | ma bar!(…) macro_rules! bar | 602 | ma bar!(…) macro_rules! bar |
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 35af354b0..0134ff219 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -7,6 +7,7 @@ use ide_db::helpers::{ | |||
7 | insert_use::{self, ImportScope, MergeBehavior}, | 7 | insert_use::{self, ImportScope, MergeBehavior}, |
8 | mod_path_to_ast, SnippetCap, | 8 | mod_path_to_ast, SnippetCap, |
9 | }; | 9 | }; |
10 | use stdx::assert_never; | ||
10 | use syntax::{algo, TextRange}; | 11 | use syntax::{algo, TextRange}; |
11 | use text_edit::TextEdit; | 12 | use text_edit::TextEdit; |
12 | 13 | ||
@@ -396,6 +397,9 @@ impl Builder { | |||
396 | } | 397 | } |
397 | pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { | 398 | pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { |
398 | self.detail = detail.map(Into::into); | 399 | self.detail = detail.map(Into::into); |
400 | if let Some(detail) = &self.detail { | ||
401 | assert_never!(detail.contains('\n'), "multiline detail: {}", detail); | ||
402 | } | ||
399 | self | 403 | self |
400 | } | 404 | } |
401 | #[allow(unused)] | 405 | #[allow(unused)] |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 3af3c59d8..bf42654a8 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -70,6 +70,11 @@ fn setup_logging(log_file: Option<PathBuf>) -> Result<()> { | |||
70 | tracing_setup::setup_tracing()?; | 70 | tracing_setup::setup_tracing()?; |
71 | 71 | ||
72 | profile::init(); | 72 | profile::init(); |
73 | |||
74 | if !cfg!(debug_assertions) { | ||
75 | stdx::set_assert_hook(|loc, args| log::error!("assertion failed at {}: {}", loc, args)); | ||
76 | } | ||
77 | |||
73 | Ok(()) | 78 | Ok(()) |
74 | } | 79 | } |
75 | 80 | ||
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index d9a62e943..1ff2559bb 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -4,6 +4,8 @@ use std::{cmp::Ordering, ops, process, time::Instant}; | |||
4 | mod macros; | 4 | mod macros; |
5 | pub mod panic_context; | 5 | pub mod panic_context; |
6 | 6 | ||
7 | pub use crate::macros::{on_assert_failure, set_assert_hook}; | ||
8 | |||
7 | #[inline(always)] | 9 | #[inline(always)] |
8 | pub fn is_ci() -> bool { | 10 | pub fn is_ci() -> bool { |
9 | option_env!("CI").is_some() | 11 | option_env!("CI").is_some() |
diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index f5ee3484b..263b938e3 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs | |||
@@ -1,4 +1,9 @@ | |||
1 | //! Convenience macros. | 1 | //! Convenience macros. |
2 | |||
3 | use std::{ | ||
4 | fmt, mem, panic, | ||
5 | sync::atomic::{AtomicUsize, Ordering::SeqCst}, | ||
6 | }; | ||
2 | #[macro_export] | 7 | #[macro_export] |
3 | macro_rules! eprintln { | 8 | macro_rules! eprintln { |
4 | ($($tt:tt)*) => {{ | 9 | ($($tt:tt)*) => {{ |
@@ -44,3 +49,50 @@ macro_rules! impl_from { | |||
44 | )* | 49 | )* |
45 | } | 50 | } |
46 | } | 51 | } |
52 | |||
53 | /// A version of `assert!` macro which allows to handle an assertion failure. | ||
54 | /// | ||
55 | /// In release mode, it returns the condition and logs an error. | ||
56 | /// | ||
57 | /// ``` | ||
58 | /// if assert_never!(impossible) { | ||
59 | /// // Heh, this shouldn't have happened, but lets try to soldier on... | ||
60 | /// return None; | ||
61 | /// } | ||
62 | /// ``` | ||
63 | /// | ||
64 | /// Rust analyzer is a long-running process, and crashing really isn't an option. | ||
65 | /// | ||
66 | /// Shamelessly stolen from: https://www.sqlite.org/assert.html | ||
67 | #[macro_export] | ||
68 | macro_rules! assert_never { | ||
69 | ($cond:expr) => { $crate::assert_always!($cond, "") }; | ||
70 | ($cond:expr, $($fmt:tt)*) => {{ | ||
71 | let value = $cond; | ||
72 | if value { | ||
73 | $crate::on_assert_failure( | ||
74 | format_args!($($fmt)*) | ||
75 | ); | ||
76 | } | ||
77 | value | ||
78 | }}; | ||
79 | } | ||
80 | |||
81 | type AssertHook = fn(&panic::Location<'_>, fmt::Arguments<'_>); | ||
82 | static HOOK: AtomicUsize = AtomicUsize::new(0); | ||
83 | |||
84 | pub fn set_assert_hook(hook: AssertHook) { | ||
85 | HOOK.store(hook as usize, SeqCst); | ||
86 | } | ||
87 | |||
88 | #[cold] | ||
89 | #[track_caller] | ||
90 | pub fn on_assert_failure(args: fmt::Arguments) { | ||
91 | let hook: usize = HOOK.load(SeqCst); | ||
92 | if hook == 0 { | ||
93 | panic!("\n assertion failed: {}\n", args); | ||
94 | } | ||
95 | |||
96 | let hook: AssertHook = unsafe { mem::transmute::<usize, AssertHook>(hook) }; | ||
97 | hook(panic::Location::caller(), args) | ||
98 | } | ||
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs index 391647fc6..cd956d950 100644 --- a/crates/syntax/src/display.rs +++ b/crates/syntax/src/display.rs | |||
@@ -80,7 +80,7 @@ pub fn macro_label(node: &ast::Macro) -> String { | |||
80 | let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); | 80 | let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); |
81 | match node { | 81 | match node { |
82 | ast::Macro::MacroRules(node) => { | 82 | ast::Macro::MacroRules(node) => { |
83 | let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; | 83 | let vis = if node.has_atom_attr("macro_export") { "#[macro_export] " } else { "" }; |
84 | format!("{}macro_rules! {}", vis, name) | 84 | format!("{}macro_rules! {}", vis, name) |
85 | } | 85 | } |
86 | ast::Macro::MacroDef(node) => { | 86 | ast::Macro::MacroDef(node) => { |