Skip to main content

mago_analyzer/plugin/libraries/stdlib/random/
rand.rs

1//! `rand()` and `mt_rand()` return type provider.
2
3use mago_codex::ttype::get_int_range;
4use mago_codex::ttype::union::TUnion;
5
6use crate::plugin::context::InvocationInfo;
7use crate::plugin::context::ProviderContext;
8use crate::plugin::provider::Provider;
9use crate::plugin::provider::ProviderMeta;
10use crate::plugin::provider::function::FunctionReturnTypeProvider;
11use crate::plugin::provider::function::FunctionTarget;
12
13static META: ProviderMeta =
14    ProviderMeta::new("php::random::rand", "rand/mt_rand", "Returns int range based on min/max arguments");
15
16static TARGETS: [&str; 2] = ["rand", "mt_rand"];
17
18/// Provider for the `rand()` and `mt_rand()` functions.
19///
20/// Returns an int range based on the min/max arguments.
21#[derive(Default)]
22pub struct RandProvider;
23
24impl Provider for RandProvider {
25    fn meta() -> &'static ProviderMeta {
26        &META
27    }
28}
29
30impl FunctionReturnTypeProvider for RandProvider {
31    fn targets() -> FunctionTarget {
32        FunctionTarget::ExactMultiple(&TARGETS)
33    }
34
35    fn get_return_type(
36        &self,
37        context: &ProviderContext<'_, '_, '_>,
38        invocation: &InvocationInfo<'_, '_, '_>,
39    ) -> Option<TUnion> {
40        if invocation.has_no_arguments() {
41            return Some(get_int_range(Some(0), None));
42        }
43
44        let min_argument = invocation.get_argument(0, &["min"])?;
45        let min_argument_type = context.get_expression_type(min_argument)?;
46        let min_argument_integer = min_argument_type.get_single_int()?;
47
48        let max_argument = invocation.get_argument(1, &["max"])?;
49        let max_argument_type = context.get_expression_type(max_argument)?;
50        let max_argument_integer = max_argument_type.get_single_int()?;
51
52        let minimum_value = min_argument_integer.get_minimum_value()?;
53        let maximum_value = max_argument_integer.get_maximum_value();
54
55        Some(get_int_range(Some(minimum_value), maximum_value))
56    }
57}