mago_analyzer/plugin/hook/call.rs
1//! Call hooks for function and method call events.
2
3use mago_syntax::cst::FunctionCall;
4use mago_syntax::cst::MethodCall;
5use mago_syntax::cst::NullSafeMethodCall;
6use mago_syntax::cst::StaticMethodCall;
7
8use crate::plugin::context::HookContext;
9use crate::plugin::hook::ExpressionHookResult;
10use crate::plugin::hook::HookResult;
11use crate::plugin::provider::Provider;
12
13/// Hook trait for intercepting function call analysis.
14///
15/// This hook receives the real AST function call node and full mutable context,
16/// allowing hooks to inspect calls, report issues, modify analysis state,
17/// and optionally skip analysis with a custom return type.
18pub trait FunctionCallHook: Provider {
19 /// Called before a function call is analyzed.
20 ///
21 /// Return `ExpressionHookResult::Continue` to proceed with normal analysis,
22 /// `ExpressionHookResult::Skip` to skip analysis (type will be `mixed`), or
23 /// `ExpressionHookResult::SkipWithType(ty)` to skip with a custom return type.
24 ///
25 /// # Errors
26 ///
27 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
28 fn before_function_call(
29 &self,
30 _call: &FunctionCall<'_>,
31 _context: &mut HookContext<'_, '_>,
32 ) -> HookResult<ExpressionHookResult> {
33 Ok(ExpressionHookResult::Continue)
34 }
35
36 /// Called after a function call has been analyzed.
37 ///
38 /// # Errors
39 ///
40 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
41 fn after_function_call(&self, _call: &FunctionCall<'_>, _context: &mut HookContext<'_, '_>) -> HookResult<()> {
42 Ok(())
43 }
44}
45
46/// Hook trait for intercepting method call analysis.
47///
48/// This hook receives the real AST method call node and full mutable context,
49/// allowing hooks to inspect calls, report issues, modify analysis state,
50/// and optionally skip analysis with a custom return type.
51pub trait MethodCallHook: Provider {
52 /// Called before a method call is analyzed.
53 ///
54 /// Return `ExpressionHookResult::Continue` to proceed with normal analysis,
55 /// `ExpressionHookResult::Skip` to skip analysis (type will be `mixed`), or
56 /// `ExpressionHookResult::SkipWithType(ty)` to skip with a custom return type.
57 ///
58 /// # Errors
59 ///
60 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
61 fn before_method_call(
62 &self,
63 _call: &MethodCall<'_>,
64 _context: &mut HookContext<'_, '_>,
65 ) -> HookResult<ExpressionHookResult> {
66 Ok(ExpressionHookResult::Continue)
67 }
68
69 /// Called after a method call has been analyzed.
70 ///
71 /// # Errors
72 ///
73 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
74 fn after_method_call(&self, _call: &MethodCall<'_>, _context: &mut HookContext<'_, '_>) -> HookResult<()> {
75 Ok(())
76 }
77}
78
79/// Hook trait for intercepting static method call analysis.
80pub trait StaticMethodCallHook: Provider {
81 /// Called before a static method call is analyzed.
82 ///
83 /// # Errors
84 ///
85 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
86 fn before_static_method_call(
87 &self,
88 _call: &StaticMethodCall<'_>,
89 _context: &mut HookContext<'_, '_>,
90 ) -> HookResult<ExpressionHookResult> {
91 Ok(ExpressionHookResult::Continue)
92 }
93
94 /// Called after a static method call has been analyzed.
95 ///
96 /// # Errors
97 ///
98 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
99 fn after_static_method_call(
100 &self,
101 _call: &StaticMethodCall<'_>,
102 _context: &mut HookContext<'_, '_>,
103 ) -> HookResult<()> {
104 Ok(())
105 }
106}
107
108/// Hook trait for intercepting nullsafe method call analysis.
109pub trait NullSafeMethodCallHook: Provider {
110 /// Called before a nullsafe method call is analyzed.
111 ///
112 /// # Errors
113 ///
114 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
115 fn before_nullsafe_method_call(
116 &self,
117 _call: &NullSafeMethodCall<'_>,
118 _context: &mut HookContext<'_, '_>,
119 ) -> HookResult<ExpressionHookResult> {
120 Ok(ExpressionHookResult::Continue)
121 }
122
123 /// Called after a nullsafe method call has been analyzed.
124 ///
125 /// # Errors
126 ///
127 /// Returns [`HookError`] if the underlying plugin implementation propagates one.
128 fn after_nullsafe_method_call(
129 &self,
130 _call: &NullSafeMethodCall<'_>,
131 _context: &mut HookContext<'_, '_>,
132 ) -> HookResult<()> {
133 Ok(())
134 }
135}