Skip to main content

mago_analyzer/plugin/libraries/stdlib/string/
strlen.rs

1//! `strlen()` return type provider.
2
3use mago_codex::ttype::get_literal_int;
4use mago_codex::ttype::get_non_negative_int;
5use mago_codex::ttype::union::TUnion;
6
7use crate::plugin::context::InvocationInfo;
8use crate::plugin::context::ProviderContext;
9use crate::plugin::provider::Provider;
10use crate::plugin::provider::ProviderMeta;
11use crate::plugin::provider::function::FunctionReturnTypeProvider;
12use crate::plugin::provider::function::FunctionTarget;
13
14static META: ProviderMeta = ProviderMeta::new(
15    "php::string::strlen",
16    "strlen",
17    "Returns a non-negative integer, or a literal length for literal strings",
18);
19
20#[derive(Default)]
21pub struct StrlenProvider;
22
23impl Provider for StrlenProvider {
24    fn meta() -> &'static ProviderMeta {
25        &META
26    }
27}
28
29impl FunctionReturnTypeProvider for StrlenProvider {
30    fn targets() -> FunctionTarget {
31        FunctionTarget::Exact(b"strlen")
32    }
33
34    fn get_return_type(
35        &self,
36        context: &ProviderContext<'_, '_, '_>,
37        invocation: &InvocationInfo<'_, '_, '_>,
38    ) -> Option<TUnion> {
39        let string_argument = invocation.get_argument(0, &[b"string"])?;
40        let string_argument_type = context.get_expression_type(string_argument)?;
41        match string_argument_type.get_single_literal_string_value() {
42            Some(string_literal) => Some(get_literal_int(string_literal.len() as i64)),
43            None => Some(get_non_negative_int()),
44        }
45    }
46}