Skip to main content

mago_analyzer/plugin/provider/
function.rs

1//! Function return type provider trait.
2
3use mago_atom::starts_with_ignore_case;
4use mago_codex::ttype::union::TUnion;
5
6use crate::plugin::context::InvocationInfo;
7use crate::plugin::context::ProviderContext;
8use crate::plugin::provider::Provider;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum FunctionTarget {
12    Exact(&'static str),
13    ExactMultiple(&'static [&'static str]),
14    Prefix(&'static str),
15    Namespace(&'static str),
16}
17
18impl FunctionTarget {
19    #[inline]
20    #[must_use]
21    pub const fn exact(name: &'static str) -> Self {
22        Self::Exact(name)
23    }
24
25    #[inline]
26    #[must_use]
27    pub const fn exact_multiple(names: &'static [&'static str]) -> Self {
28        Self::ExactMultiple(names)
29    }
30
31    #[inline]
32    #[must_use]
33    pub const fn prefix(prefix: &'static str) -> Self {
34        Self::Prefix(prefix)
35    }
36
37    #[inline]
38    #[must_use]
39    pub const fn namespace(ns: &'static str) -> Self {
40        Self::Namespace(ns)
41    }
42
43    #[must_use]
44    pub fn matches(&self, name: &str) -> bool {
45        match self {
46            FunctionTarget::Exact(target) => name.eq_ignore_ascii_case(target),
47            FunctionTarget::ExactMultiple(targets) => targets.iter().any(|target| name.eq_ignore_ascii_case(target)),
48            FunctionTarget::Prefix(prefix) => starts_with_ignore_case(name, prefix),
49            FunctionTarget::Namespace(ns) => starts_with_ignore_case(name, ns),
50        }
51    }
52
53    #[must_use]
54    pub fn get_exact_names(&self) -> Option<Vec<&'static str>> {
55        match self {
56            FunctionTarget::Exact(name) => Some(vec![*name]),
57            FunctionTarget::ExactMultiple(names) => Some(names.to_vec()),
58            FunctionTarget::Prefix(_) | FunctionTarget::Namespace(_) => None,
59        }
60    }
61
62    #[must_use]
63    pub fn is_prefix(&self) -> bool {
64        matches!(self, FunctionTarget::Prefix(_))
65    }
66
67    #[must_use]
68    pub fn is_namespace(&self) -> bool {
69        matches!(self, FunctionTarget::Namespace(_))
70    }
71
72    #[must_use]
73    pub fn get_prefix(&self) -> Option<&'static str> {
74        match self {
75            FunctionTarget::Prefix(prefix) => Some(prefix),
76            _ => None,
77        }
78    }
79
80    #[must_use]
81    pub fn get_namespace(&self) -> Option<&'static str> {
82        match self {
83            FunctionTarget::Namespace(ns) => Some(ns),
84            _ => None,
85        }
86    }
87}
88
89pub trait FunctionReturnTypeProvider: Provider {
90    fn targets() -> FunctionTarget
91    where
92        Self: Sized;
93
94    fn get_return_type(
95        &self,
96        context: &ProviderContext<'_, '_, '_>,
97        invocation: &InvocationInfo<'_, '_, '_>,
98    ) -> Option<TUnion>;
99}