MCPcopy Create free account
hub / github.com/PHPantom-dev/phpantom_lsp / extract_call_expression

Function extract_call_expression

src/completion/named_args.rs:236–315  ·  view source on GitHub ↗

Extract the call expression that precedes the opening paren at `open`. Handles: - `foo(` → `"foo"` - `$this->method(` → `"$this->method"` - `$var->method(` → `"$var->method"` - `ClassName::method(` → `"ClassName::method"` - `self::method(` / `static::method(` / `parent::method(` → as-is - `new ClassName(` → `"new ClassName"` - `(new Foo())->method(` → `"$this->method"` etc. — simplified

(chars: &[char], open: usize)

Source from the content-addressed store, hash-verified

234/// - `new ClassName(` → `"new ClassName"`
235/// - `(new Foo())->method(` → `"$this->method"` etc. — simplified
236pub fn extract_call_expression(chars: &[char], open: usize) -> Option<String> {
237 if open == 0 {
238 return None;
239 }
240
241 let mut i = open;
242
243 // Skip whitespace before `(`
244 while i > 0 && chars[i - 1] == ' ' {
245 i -= 1;
246 }
247
248 if i == 0 {
249 return None;
250 }
251
252 // ── If preceded by `)`, this is a chained call like `foo()->bar(`.
253 // We won't try to resolve through call chains for named args — the
254 // complexity is high and the user can rely on member completion.
255 // But we DO need to handle `(new Foo)(` — skip for now.
256 if chars[i - 1] == ')' {
257 return None;
258 }
259
260 // ── Read the identifier (function/method name) ──────────────────
261 let ident_end = i;
262 while i > 0 && (chars[i - 1].is_alphanumeric() || chars[i - 1] == '_' || chars[i - 1] == '\\') {
263 i -= 1;
264 }
265 if i == ident_end {
266 return None;
267 }
268 let ident: String = chars[i..ident_end].iter().collect();
269
270 // ── Check what precedes the identifier ──────────────────────────
271
272 // Instance method: `->method(`
273 if i >= 2 && chars[i - 2] == '-' && chars[i - 1] == '>' {
274 let subject = extract_subject_before_arrow(chars, i - 2);
275 if !subject.is_empty() {
276 return Some(format!("{}->{}", subject, ident));
277 }
278 return None;
279 }
280
281 // Null-safe method: `?->method(`
282 if i >= 3 && chars[i - 3] == '?' && chars[i - 2] == '-' && chars[i - 1] == '>' {
283 let subject = extract_subject_before_arrow(chars, i - 3);
284 if !subject.is_empty() {
285 return Some(format!("{}->{}", subject, ident));
286 }
287 return None;
288 }
289
290 // Static method: `::method(`
291 if i >= 2 && chars[i - 2] == ':' && chars[i - 1] == ':' {
292 let class_name = extract_class_name_backward(chars, i - 2);
293 if !class_name.is_empty() {

Callers 2

detect_named_arg_contextFunction · 0.85

Calls 4

iterMethod · 0.80
is_emptyMethod · 0.45

Tested by

no test coverage detected