Build an LSP snippet string for a PHP attribute constructor. Attributes are syntactic sugar for `new ClassName(...)` with the `new` dropped, so they take the same constructor parameters. Unlike regular `new` snippets, attribute snippets use **named arguments** for every parameter (both required and optional with non-trivial defaults). Named arguments are safe here because both attributes and nam
(name: &str, params: &[ParameterInfo])
| 106 | /// | `("DataProvider", &[req(string $methodName)])` | `"DataProvider(${1:'methodName'})$0"` | |
| 107 | /// | `("Route", &[req(string $path), opt(array $methods)])` | `"Route(${1:'path'})$0"` | |
| 108 | pub(crate) fn build_attribute_snippet(name: &str, params: &[ParameterInfo]) -> String { |
| 109 | // Collect parameters worth including: all required ones, plus |
| 110 | // optional ones only when they have no default (rare but possible). |
| 111 | // Parameters with defaults are omitted — the user can add them via |
| 112 | // signature help if needed. |
| 113 | let required: Vec<&ParameterInfo> = params.iter().filter(|p| p.is_required).collect(); |
| 114 | |
| 115 | if required.is_empty() { |
| 116 | // No required constructor params — insert the bare attribute |
| 117 | // name without parentheses. `#[Override]` not `#[Override()]`. |
| 118 | name.to_string() |
| 119 | } else { |
| 120 | let placeholders: Vec<String> = required |
| 121 | .iter() |
| 122 | .enumerate() |
| 123 | .map(|(i, p)| { |
| 124 | let arg_name = p.name.strip_prefix('$').unwrap_or(&*p.name); |
| 125 | let (prefix, placeholder, suffix) = attribute_placeholder(p); |
| 126 | format!("{arg_name}: {prefix}${{{}:{}}}{suffix}", i + 1, placeholder) |
| 127 | }) |
| 128 | .collect(); |
| 129 | format!("{name}({})$0", placeholders.join(", ")) |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | /// Choose a sensible placeholder value for an attribute constructor parameter. |
| 134 | /// |
no test coverage detected