Skip to main content

mago_analyzer/plugin/libraries/stdlib/reflection/
method_invoke.rs

1//! `ReflectionMethod<T>::invoke()` / `invokeArgs()` return type provider.
2
3use mago_codex::ttype::union::TUnion;
4
5use crate::plugin::context::InvocationInfo;
6use crate::plugin::context::ProviderContext;
7use crate::plugin::provider::Provider;
8use crate::plugin::provider::ProviderMeta;
9use crate::plugin::provider::method::MethodReturnTypeProvider;
10use crate::plugin::provider::method::MethodTarget;
11
12static META: ProviderMeta = ProviderMeta::new(
13    "reflection::method::invoke",
14    "ReflectionMethod::invoke",
15    "Returns the union of method return types of the reflected class",
16);
17
18static TARGETS: [MethodTarget; 2] = [MethodTarget::any_class(b"invoke"), MethodTarget::any_class(b"invokeArgs")];
19
20/// Provider for `ReflectionMethod<T>::invoke()` and `invokeArgs()`.
21///
22/// A `ReflectionMethod<T>` does not track *which* method it is, so invoking it
23/// returns the union of the return types of every method on `T` (e.g. invoking
24/// some method of a class whose only method returns `'Hello'` yields `'Hello'`)
25/// instead of `mixed`.
26#[derive(Default)]
27pub struct ReflectionMethodInvokeProvider;
28
29impl Provider for ReflectionMethodInvokeProvider {
30    fn meta() -> &'static ProviderMeta {
31        &META
32    }
33}
34
35impl MethodReturnTypeProvider for ReflectionMethodInvokeProvider {
36    fn targets() -> &'static [MethodTarget] {
37        &TARGETS
38    }
39
40    fn get_return_type(
41        &self,
42        context: &ProviderContext<'_, '_, '_>,
43        _class_name: &[u8],
44        _method_name: &[u8],
45        invocation: &InvocationInfo<'_, '_, '_>,
46    ) -> Option<TUnion> {
47        let reflected_class = super::reflected_class_name(context, invocation, b"ReflectionMethod")?;
48
49        super::method_return_union(context.codebase(), reflected_class)
50    }
51}