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