php_lsp/analysis/
callable_info.rs1pub(crate) struct CallableInfo {
2 pub params: String,
3 pub return_type: Option<String>,
4 pub documentation: Option<String>,
5}
6
7pub(crate) fn format_declared_params(params: &[mir_analyzer::DeclaredParam]) -> String {
8 params
9 .iter()
10 .map(|p| {
11 let mut s = String::new();
12 if let Some(ty) = &p.ty {
13 s.push_str(&format!("{ty} "));
14 }
15 if p.is_variadic {
16 s.push_str("...");
17 }
18 s.push_str(&format!("${}", p.name.as_str().trim_start_matches('$')));
19 if let Some(text) = &p.default_text {
20 s.push_str(&format!(" = {text}"));
21 } else if p.has_default {
22 s.push_str(" = ...");
23 }
24 s
25 })
26 .collect::<Vec<_>>()
27 .join(", ")
28}
29
30pub(crate) fn callable_info_for_name(
31 db: &mir_analyzer::db::MirDbStorage,
32 symbol: &mir_analyzer::Name,
33) -> Option<CallableInfo> {
34 match symbol {
35 mir_analyzer::Name::Function(fqn) => {
36 let short = fqn.rsplit('\\').next().unwrap_or(fqn.as_ref());
37 if mir_analyzer::is_builtin_function(short) {
38 return None;
39 }
40 let f = mir_analyzer::db::find_function(
41 db,
42 mir_analyzer::db::Fqcn::from_str(db, fqn.as_ref()),
43 )?;
44 Some(CallableInfo {
45 params: format_declared_params(&f.params),
46 return_type: f.effective_return_type().map(ToString::to_string),
47 documentation: f.docstring.as_deref().map(str::to_string),
48 })
49 }
50 mir_analyzer::Name::Method { class, name } => {
51 let (_, m) = mir_analyzer::db::find_method_in_chain(
52 db,
53 mir_analyzer::db::Fqcn::from_str(db, class.as_ref()),
54 name.as_ref(),
55 )?;
56 Some(CallableInfo {
57 params: format_declared_params(&m.params),
58 return_type: m
59 .return_type
60 .as_deref()
61 .or(m.inferred_return_type.as_deref())
62 .map(ToString::to_string),
63 documentation: m.docstring.as_deref().map(str::to_string),
64 })
65 }
66 mir_analyzer::Name::Class(fqcn) => {
67 let (_, m) = mir_analyzer::db::find_method_in_chain(
68 db,
69 mir_analyzer::db::Fqcn::from_str(db, fqcn.as_ref()),
70 "__construct",
71 )?;
72 Some(CallableInfo {
73 params: format_declared_params(&m.params),
74 return_type: None,
75 documentation: m.docstring.as_deref().map(str::to_string),
76 })
77 }
78 _ => None,
79 }
80}