Skip to main content

mir_php/
stubs.rs

1/// Built-in PHP function and class stubs.
2///
3/// Provides arities for core PHP functions and common extensions so the
4/// analyser does not flag standard-library calls as undefined.
5///
6/// Each entry is `(name, required_args, max_args)`.
7/// `usize::MAX` means variadic (no upper bound).
8
9/// Arity bounds for a built-in callable.
10#[derive(Debug, Clone, Copy)]
11pub struct Arity {
12    pub required: usize,
13    pub max: usize,
14}
15
16/// Look up the arity of a built-in PHP function by name.
17/// Returns `None` if the name is not a known built-in.
18pub fn function_arity(name: &str) -> Option<Arity> {
19    BUILTIN_FUNCTIONS
20        .binary_search_by_key(&name, |&(n, _, _)| n)
21        .ok()
22        .map(|i| {
23            let (_, req, max) = BUILTIN_FUNCTIONS[i];
24            Arity { required: req, max }
25        })
26}
27
28/// True if `name` is a known built-in class / interface / exception.
29pub fn is_builtin_class(name: &str) -> bool {
30    BUILTIN_CLASSES
31        .binary_search_by_key(&name, |&n| n)
32        .is_ok()
33}
34
35/// Sorted list of built-in PHP function names with (required, max) arg counts.
36/// `usize::MAX` means variadic. Must stay sorted for binary search.
37pub static BUILTIN_FUNCTIONS: &[(&str, usize, usize)] = &[
38    ("abs", 1, 1),
39    ("array_chunk", 2, 3),
40    ("array_column", 2, 3),
41    ("array_combine", 2, 2),
42    ("array_diff", 1, usize::MAX),
43    ("array_diff_assoc", 1, usize::MAX),
44    ("array_diff_key", 1, usize::MAX),
45    ("array_fill", 3, 3),
46    ("array_filter", 1, 3),
47    ("array_flip", 1, 1),
48    ("array_intersect", 1, usize::MAX),
49    ("array_intersect_key", 1, usize::MAX),
50    ("array_key_exists", 2, 2),
51    ("array_key_first", 1, 1),
52    ("array_key_last", 1, 1),
53    ("array_keys", 1, 3),
54    ("array_map", 2, usize::MAX),
55    ("array_merge", 0, usize::MAX),
56    ("array_merge_recursive", 0, usize::MAX),
57    ("array_pad", 3, 3),
58    ("array_pop", 1, 1),
59    ("array_push", 1, usize::MAX),
60    ("array_replace", 1, usize::MAX),
61    ("array_reverse", 1, 2),
62    ("array_search", 2, 3),
63    ("array_shift", 1, 1),
64    ("array_slice", 2, 4),
65    ("array_splice", 2, 4),
66    ("array_sum", 1, 1),
67    ("array_unique", 1, 2),
68    ("array_unshift", 1, usize::MAX),
69    ("array_values", 1, 1),
70    ("arsort", 1, 2),
71    ("asort", 1, 2),
72    ("base64_decode", 1, 2),
73    ("base64_encode", 1, 1),
74    ("base_convert", 3, 3),
75    ("basename", 1, 2),
76    ("ceil", 1, 1),
77    ("chr", 1, 1),
78    ("chunk_split", 1, 3),
79    ("class_alias", 2, 3),
80    ("class_exists", 1, 2),
81    ("class_implements", 1, 2),
82    ("class_parents", 1, 2),
83    ("compact", 1, usize::MAX),
84    ("copy", 2, 3),
85    ("count", 1, 2),
86    ("ctype_alpha", 1, 1),
87    ("ctype_digit", 1, 1),
88    ("ctype_lower", 1, 1),
89    ("ctype_upper", 1, 1),
90    ("curl_close", 1, 1),
91    ("curl_error", 1, 1),
92    ("curl_exec", 1, 1),
93    ("curl_getinfo", 1, 2),
94    ("curl_init", 0, 1),
95    ("curl_setopt", 3, 3),
96    ("curl_setopt_array", 2, 2),
97    ("date", 1, 2),
98    ("date_create", 0, 2),
99    ("date_diff", 2, 3),
100    ("date_format", 2, 2),
101    ("defined", 1, 1),
102    ("dirname", 1, 2),
103    ("empty", 1, 1),
104    ("end", 1, 1),
105    ("error_log", 1, 4),
106    ("error_reporting", 0, 1),
107    ("exec", 1, 3),
108    ("explode", 2, 3),
109    ("extension_loaded", 1, 1),
110    ("extract", 1, 3),
111    ("fclose", 1, 1),
112    ("feof", 1, 1),
113    ("fgets", 1, 2),
114    ("file", 1, 3),
115    ("file_exists", 1, 1),
116    ("file_get_contents", 1, 5),
117    ("file_put_contents", 2, 4),
118    ("filemtime", 1, 1),
119    ("filesize", 1, 1),
120    ("floor", 1, 1),
121    ("fopen", 2, 4),
122    ("fread", 2, 2),
123    ("fseek", 2, 3),
124    ("function_exists", 1, 2),
125    ("fwrite", 2, 3),
126    ("get_class", 0, 1),
127    ("get_class_methods", 1, 1),
128    ("get_declared_classes", 0, 0),
129    ("get_object_vars", 1, 1),
130    ("getenv", 0, 2),
131    ("gettype", 1, 1),
132    ("glob", 1, 2),
133    ("gmdate", 1, 2),
134    ("header", 1, 3),
135    ("htmlentities", 1, 4),
136    ("htmlspecialchars", 1, 4),
137    ("htmlspecialchars_decode", 1, 2),
138    ("http_response_code", 0, 1),
139    ("implode", 1, 2),
140    ("in_array", 2, 3),
141    ("ini_get", 1, 1),
142    ("ini_set", 2, 2),
143    ("interface_exists", 1, 2),
144    ("intval", 1, 2),
145    ("is_a", 2, 3),
146    ("is_array", 1, 1),
147    ("is_bool", 1, 1),
148    ("is_callable", 1, 3),
149    ("is_dir", 1, 1),
150    ("is_file", 1, 1),
151    ("is_float", 1, 1),
152    ("is_int", 1, 1),
153    ("is_null", 1, 1),
154    ("is_numeric", 1, 1),
155    ("is_object", 1, 1),
156    ("is_readable", 1, 1),
157    ("is_string", 1, 1),
158    ("is_subclass_of", 2, 3),
159    ("is_writable", 1, 1),
160    ("json_decode", 1, 4),
161    ("json_encode", 1, 3),
162    ("json_last_error", 0, 0),
163    ("json_last_error_msg", 0, 0),
164    ("krsort", 1, 2),
165    ("ksort", 1, 2),
166    ("lcfirst", 1, 1),
167    ("ltrim", 1, 2),
168    ("max", 1, usize::MAX),
169    ("mb_convert_encoding", 2, 3),
170    ("mb_detect_encoding", 1, 3),
171    ("mb_internal_encoding", 0, 1),
172    ("mb_strlen", 1, 2),
173    ("mb_strpos", 2, 4),
174    ("mb_strrpos", 2, 4),
175    ("mb_strtolower", 1, 2),
176    ("mb_strtoupper", 1, 2),
177    ("mb_substr", 2, 4),
178    ("md5", 1, 2),
179    ("method_exists", 2, 2),
180    ("microtime", 0, 1),
181    ("min", 1, usize::MAX),
182    ("mkdir", 1, 4),
183    ("mktime", 0, 6),
184    ("number_format", 1, 4),
185    ("ob_end_clean", 0, 0),
186    ("ob_end_flush", 0, 0),
187    ("ob_get_clean", 0, 0),
188    ("ob_get_contents", 0, 0),
189    ("ob_start", 0, 3),
190    ("ord", 1, 1),
191    ("pack", 1, usize::MAX),
192    ("parse_url", 1, 2),
193    ("pathinfo", 1, 2),
194    ("phpversion", 0, 1),
195    ("preg_match", 2, 5),
196    ("preg_match_all", 2, 5),
197    ("preg_quote", 1, 2),
198    ("preg_replace", 3, 5),
199    ("preg_replace_callback", 3, 5),
200    ("preg_split", 2, 4),
201    ("print_r", 1, 2),
202    ("property_exists", 2, 2),
203    ("range", 2, 3),
204    ("rawurldecode", 1, 1),
205    ("rawurlencode", 1, 1),
206    ("realpath", 1, 1),
207    ("rename", 2, 3),
208    ("reset", 1, 1),
209    ("rmdir", 1, 2),
210    ("round", 1, 3),
211    ("rtrim", 1, 2),
212    ("serialize", 1, 1),
213    ("session_destroy", 0, 0),
214    ("session_id", 0, 1),
215    ("session_name", 0, 1),
216    ("session_start", 0, 1),
217    ("setcookie", 1, 7),
218    ("sha1", 1, 2),
219    ("sleep", 1, 1),
220    ("sort", 1, 2),
221    ("sprintf", 1, usize::MAX),
222    ("sqrt", 1, 1),
223    ("srand", 0, 2),
224    ("str_contains", 2, 2),
225    ("str_ends_with", 2, 2),
226    ("str_pad", 2, 4),
227    ("str_repeat", 2, 2),
228    ("str_replace", 3, 4),
229    ("str_split", 1, 2),
230    ("str_starts_with", 2, 2),
231    ("str_word_count", 1, 3),
232    ("strcasecmp", 2, 2),
233    ("strcmp", 2, 2),
234    ("strip_tags", 1, 2),
235    ("stripslashes", 1, 1),
236    ("strlen", 1, 1),
237    ("strncmp", 3, 3),
238    ("strpos", 2, 3),
239    ("strrchr", 2, 2),
240    ("strrev", 1, 1),
241    ("strrpos", 2, 3),
242    ("strstr", 2, 3),
243    ("strtok", 1, 2),
244    ("strtolower", 1, 1),
245    ("strtotime", 1, 2),
246    ("strtoupper", 1, 1),
247    ("strval", 1, 1),
248    ("substr", 2, 3),
249    ("substr_count", 2, 4),
250    ("substr_replace", 3, 4),
251    ("sys_get_temp_dir", 0, 0),
252    ("time", 0, 0),
253    ("touch", 1, 3),
254    ("trigger_error", 1, 2),
255    ("trim", 1, 2),
256    ("uasort", 2, 2),
257    ("ucfirst", 1, 1),
258    ("ucwords", 1, 2),
259    ("uksort", 2, 2),
260    ("unlink", 1, 2),
261    ("unserialize", 1, 2),
262    ("urldecode", 1, 1),
263    ("urlencode", 1, 1),
264    ("usort", 2, 2),
265    ("var_dump", 1, usize::MAX),
266    ("var_export", 1, 2),
267    ("wordwrap", 1, 4),
268];
269
270/// Sorted list of built-in PHP class / interface / exception names.
271static BUILTIN_CLASSES: &[&str] = &[
272    "ArrayAccess",
273    "ArrayIterator",
274    "ArrayObject",
275    "BadFunctionCallException",
276    "BadMethodCallException",
277    "Closure",
278    "Countable",
279    "DateInterval",
280    "DateTime",
281    "DateTimeImmutable",
282    "DateTimeInterface",
283    "DateTimeZone",
284    "DirectoryIterator",
285    "DomainException",
286    "Error",
287    "Exception",
288    "FilesystemIterator",
289    "Generator",
290    "GlobIterator",
291    "InfiniteIterator",
292    "InvalidArgumentException",
293    "Iterator",
294    "IteratorAggregate",
295    "JsonSerializable",
296    "LengthException",
297    "LogicException",
298    "OutOfBoundsException",
299    "OutOfRangeException",
300    "OverflowException",
301    "PDO",
302    "PDOException",
303    "PDOStatement",
304    "RangeException",
305    "RecursiveArrayIterator",
306    "RecursiveDirectoryIterator",
307    "RecursiveIterator",
308    "RecursiveIteratorIterator",
309    "ReflectionClass",
310    "ReflectionException",
311    "ReflectionFunction",
312    "ReflectionMethod",
313    "ReflectionProperty",
314    "RuntimeException",
315    "Serializable",
316    "SplDoublyLinkedList",
317    "SplFileInfo",
318    "SplFileObject",
319    "SplFixedArray",
320    "SplMaxHeap",
321    "SplMinHeap",
322    "SplPriorityQueue",
323    "SplQueue",
324    "SplStack",
325    "Stringable",
326    "Throwable",
327    "TypeError",
328    "UnderflowException",
329    "UnexpectedValueException",
330    "ValueError",
331    "WeakMap",
332    "WeakReference",
333    "stdClass",
334];
335
336#[cfg(test)]
337mod tests {
338    use super::*;
339
340    #[test]
341    fn builtin_functions_are_sorted() {
342        for pair in BUILTIN_FUNCTIONS.windows(2) {
343            assert!(
344                pair[0].0 <= pair[1].0,
345                "out of order: '{}' before '{}'",
346                pair[0].0,
347                pair[1].0
348            );
349        }
350    }
351
352    #[test]
353    fn builtin_classes_are_sorted() {
354        for pair in BUILTIN_CLASSES.windows(2) {
355            assert!(pair[0] <= pair[1], "out of order: '{}' before '{}'", pair[0], pair[1]);
356        }
357    }
358
359    #[test]
360    fn strlen_is_known() {
361        assert!(function_arity("strlen").is_some());
362    }
363
364    #[test]
365    fn pdo_is_builtin_class() {
366        assert!(is_builtin_class("PDO"));
367    }
368
369    #[test]
370    fn unknown_function_is_none() {
371        assert!(function_arity("totally_unknown_fn_xyz").is_none());
372    }
373}