aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand/src/diagnostics.rs')
-rw-r--r--crates/ra_hir_expand/src/diagnostics.rs60
1 files changed, 44 insertions, 16 deletions
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs
index 545cff9bd..84ba97b14 100644
--- a/crates/ra_hir_expand/src/diagnostics.rs
+++ b/crates/ra_hir_expand/src/diagnostics.rs
@@ -24,6 +24,9 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
24 fn message(&self) -> String; 24 fn message(&self) -> String;
25 fn source(&self) -> InFile<SyntaxNodePtr>; 25 fn source(&self) -> InFile<SyntaxNodePtr>;
26 fn as_any(&self) -> &(dyn Any + Send + 'static); 26 fn as_any(&self) -> &(dyn Any + Send + 'static);
27 fn is_experimental(&self) -> bool {
28 false
29 }
27} 30}
28 31
29pub trait AstDiagnostic { 32pub trait AstDiagnostic {
@@ -44,16 +47,48 @@ impl dyn Diagnostic {
44 47
45pub struct DiagnosticSink<'a> { 48pub struct DiagnosticSink<'a> {
46 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, 49 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
50 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,
47 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>, 51 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>,
48} 52}
49 53
50impl<'a> DiagnosticSink<'a> { 54impl<'a> DiagnosticSink<'a> {
51 /// FIXME: split `new` and `on` into a separate builder type 55 pub fn push(&mut self, d: impl Diagnostic) {
52 pub fn new(cb: impl FnMut(&dyn Diagnostic) + 'a) -> DiagnosticSink<'a> { 56 let d: &dyn Diagnostic = &d;
53 DiagnosticSink { callbacks: Vec::new(), default_callback: Box::new(cb) } 57 self._push(d);
58 }
59
60 fn _push(&mut self, d: &dyn Diagnostic) {
61 for filter in &mut self.filters {
62 if !filter(d) {
63 return;
64 }
65 }
66 for cb in &mut self.callbacks {
67 match cb(d) {
68 Ok(()) => return,
69 Err(()) => (),
70 }
71 }
72 (self.default_callback)(d)
54 } 73 }
74}
55 75
56 pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> DiagnosticSink<'a> { 76pub struct DiagnosticSinkBuilder<'a> {
77 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
78 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,
79}
80
81impl<'a> DiagnosticSinkBuilder<'a> {
82 pub fn new() -> Self {
83 Self { callbacks: Vec::new(), filters: Vec::new() }
84 }
85
86 pub fn filter<F: FnMut(&dyn Diagnostic) -> bool + 'a>(mut self, cb: F) -> Self {
87 self.filters.push(Box::new(cb));
88 self
89 }
90
91 pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> Self {
57 let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() { 92 let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() {
58 Some(d) => { 93 Some(d) => {
59 cb(d); 94 cb(d);
@@ -65,18 +100,11 @@ impl<'a> DiagnosticSink<'a> {
65 self 100 self
66 } 101 }
67 102
68 pub fn push(&mut self, d: impl Diagnostic) { 103 pub fn build<F: FnMut(&dyn Diagnostic) + 'a>(self, default_callback: F) -> DiagnosticSink<'a> {
69 let d: &dyn Diagnostic = &d; 104 DiagnosticSink {
70 self._push(d); 105 callbacks: self.callbacks,
71 } 106 filters: self.filters,
72 107 default_callback: Box::new(default_callback),
73 fn _push(&mut self, d: &dyn Diagnostic) {
74 for cb in self.callbacks.iter_mut() {
75 match cb(d) {
76 Ok(()) => return,
77 Err(()) => (),
78 }
79 } 108 }
80 (self.default_callback)(d)
81 } 109 }
82} 110}