1use std::fmt::{Debug, Formatter, Result};
2use std::sync::Mutex;
3
4use crate::decl_engine::DeclRefFunction;
5use crate::language::parsed::MethodName;
6use crate::semantic_analysis::TypeCheckContext;
7use crate::{TypeBinding, TypeId};
8
9pub trait Observer {
10 fn on_trace(&self, _msg: &str) {}
11
12 fn on_before_method_resolution(
13 &self,
14 _ctx: &TypeCheckContext<'_>,
15 _method_name: &TypeBinding<MethodName>,
16 _args_types: &[TypeId],
17 ) {
18 }
19
20 fn on_after_method_resolution(
21 &self,
22 _ctx: &TypeCheckContext<'_>,
23 _method_name: &TypeBinding<MethodName>,
24 _args_types: &[TypeId],
25 _new_ref: DeclRefFunction,
26 _new_type_id: TypeId,
27 ) {
28 }
29}
30
31#[derive(Default)]
32pub struct ObservabilityEngine {
33 observer: Mutex<Option<Box<dyn Observer>>>,
34 trace: Mutex<bool>,
35}
36
37unsafe impl Send for ObservabilityEngine {}
38unsafe impl Sync for ObservabilityEngine {}
39
40impl Debug for ObservabilityEngine {
41 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
42 f.debug_struct("ObservabilityEngine")
43 .field("trace", &self.trace)
44 .finish()
45 }
46}
47
48impl ObservabilityEngine {
49 pub fn set_observer(&self, observer: Box<dyn Observer>) {
50 let mut obs = self.observer.lock().unwrap();
51 *obs = Some(observer);
52 }
53
54 pub fn raise_on_before_method_resolution(
55 &self,
56 ctx: &TypeCheckContext,
57 method_name: &TypeBinding<MethodName>,
58 arguments_types: &[TypeId],
59 ) {
60 if let Some(obs) = self.observer.lock().unwrap().as_mut() {
61 obs.on_before_method_resolution(ctx, method_name, arguments_types);
62 }
63 }
64
65 pub fn raise_on_after_method_resolution(
66 &self,
67 ctx: &TypeCheckContext,
68 method_name: &TypeBinding<MethodName>,
69 arguments_types: &[TypeId],
70 ref_function: DeclRefFunction,
71 tid: TypeId,
72 ) {
73 if let Some(obs) = self.observer.lock().unwrap().as_mut() {
74 obs.on_after_method_resolution(ctx, method_name, arguments_types, ref_function, tid);
75 }
76 }
77
78 pub(crate) fn trace(&self, get_txt: impl FnOnce() -> String) {
79 let trace = self.trace.lock().unwrap();
80 if *trace {
81 if let Some(obs) = self.observer.lock().unwrap().as_mut() {
82 obs.on_trace(&get_txt());
83 }
84 }
85 }
86
87 pub fn enable_trace(&self, enable: bool) {
88 let mut trace = self.trace.lock().unwrap();
89 *trace = enable
90 }
91}