Choose a sensible placeholder value for an attribute constructor parameter. Returns `(prefix, placeholder, suffix)` where `prefix` and `suffix` are literal characters that surround the snippet tab stop. For string parameters this produces `'${n:methodName}'` so that typing replaces only the inner text while preserving the quotes. If the parameter has an explicit default value in source code, th
(param: &ParameterInfo)
| 141 | /// is used directly as the placeholder with no wrapping. Otherwise, |
| 142 | /// the type hint is inspected to produce a valid PHP literal. |
| 143 | fn attribute_placeholder(param: &ParameterInfo) -> (String, String, String) { |
| 144 | // Use the explicit default when available. |
| 145 | if let Some(ref default) = param.default_value { |
| 146 | return (String::new(), default.clone(), String::new()); |
| 147 | } |
| 148 | |
| 149 | // Infer from the type hint. Prefer the native hint over the |
| 150 | // docblock hint, and unwrap nullable wrappers (`?string` or |
| 151 | // `string|null` both yield `string`) via `PhpType::non_null_type()` |
| 152 | // instead of manual `?`-prefix stripping on strings. |
| 153 | let hint = param.native_type_hint.as_ref().or(param.type_hint.as_ref()); |
| 154 | let base_type = match hint { |
| 155 | Some(t) => match t.non_null_type() { |
| 156 | Some(inner) => inner, |
| 157 | None => t.clone(), |
| 158 | }, |
| 159 | None => { |
| 160 | // No type hint — use the bare parameter name. |
| 161 | let name = param.name.strip_prefix('$').unwrap_or(&*param.name); |
| 162 | return (String::new(), name.to_string(), String::new()); |
| 163 | } |
| 164 | }; |
| 165 | |
| 166 | if base_type.is_string_type() { |
| 167 | // Use the parameter name (without $) as a descriptive |
| 168 | // placeholder. Quotes sit outside the tab stop so typing |
| 169 | // replaces only the inner text: `'${1:methodName}'`. |
| 170 | let name = param.name.strip_prefix('$').unwrap_or(&*param.name); |
| 171 | return ("'".to_string(), name.to_string(), "'".to_string()); |
| 172 | } |
| 173 | if base_type.is_bool() { |
| 174 | return (String::new(), "false".to_string(), String::new()); |
| 175 | } |
| 176 | if base_type.is_int() { |
| 177 | return (String::new(), "0".to_string(), String::new()); |
| 178 | } |
| 179 | if base_type.is_float() { |
| 180 | return (String::new(), "0.0".to_string(), String::new()); |
| 181 | } |
| 182 | if base_type.is_bare_array() { |
| 183 | return (String::new(), "[]".to_string(), String::new()); |
| 184 | } |
| 185 | // Unknown or complex type — use the bare parameter name. |
| 186 | let name = param.name.strip_prefix('$').unwrap_or(&*param.name); |
| 187 | (String::new(), name.to_string(), String::new()) |
| 188 | } |
| 189 | |
| 190 | // Re-export use-statement helpers so existing `use crate::completion::builder::{…}` |
| 191 | // imports continue to work. |
no test coverage detected