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

Function detect_named_arg_context

src/completion/named_args.rs:103–151  ·  view source on GitHub ↗

Detect whether the cursor is inside a function/method call and extract the context needed for named-argument completion. Returns `None` if the cursor is not at an eligible position (e.g. after `$`, `->`, `::`, or inside a string/comment).

(content: &str, position: Position)

Source from the content-addressed store, hash-verified

101/// Returns `None` if the cursor is not at an eligible position (e.g. after
102/// `$`, `->`, `::`, or inside a string/comment).
103pub fn detect_named_arg_context(content: &str, position: Position) -> Option<NamedArgContext> {
104 let chars: Vec<char> = content.chars().collect();
105 let cursor = position_to_char_offset(&chars, position)?;
106
107 // ── Check eligibility at cursor ─────────────────────────────────
108 // Walk backward from cursor through identifier chars to find the
109 // start of the current "word".
110 let mut word_start = cursor;
111 while word_start > 0
112 && (chars[word_start - 1].is_alphanumeric() || chars[word_start - 1] == '_')
113 {
114 word_start -= 1;
115 }
116
117 // If preceded by `$`, this is a variable — not a named arg.
118 if word_start > 0 && chars[word_start - 1] == '$' {
119 return None;
120 }
121
122 // If preceded by `->` or `::`, member completion handles this.
123 if word_start >= 2 && chars[word_start - 2] == '-' && chars[word_start - 1] == '>' {
124 return None;
125 }
126 if word_start >= 2 && chars[word_start - 2] == ':' && chars[word_start - 1] == ':' {
127 return None;
128 }
129
130 let prefix: String = chars[word_start..cursor].iter().collect();
131
132 // ── Find enclosing open paren ───────────────────────────────────
133 let open_paren = find_enclosing_open_paren(&chars, word_start)?;
134
135 // ── Extract call expression before `(` ──────────────────────────
136 let call_expr = extract_call_expression(&chars, open_paren)?;
137 if call_expr.is_empty() {
138 return None;
139 }
140
141 // ── Parse arguments between `(` and cursor ──────────────────────
142 let args_text: String = chars[open_paren + 1..word_start].iter().collect();
143 let (existing_named, positional_count) = parse_existing_args(&args_text);
144
145 Some(NamedArgContext {
146 call_expression: call_expr,
147 existing_named_args: existing_named,
148 positional_count,
149 prefix,
150 })
151}
152
153// Re-exported from `crate::util` for backward compatibility with
154// existing import paths.

Callers 12

context_simple_functionFunction · 0.85
context_with_prefixFunction · 0.85
context_after_positionalFunction · 0.85
context_after_named_argFunction · 0.85
context_method_callFunction · 0.85
context_static_callFunction · 0.85
context_constructorFunction · 0.85
no_context_after_arrowFunction · 0.85
context_multilineFunction · 0.85

Calls 6

position_to_char_offsetFunction · 0.85
extract_call_expressionFunction · 0.85
parse_existing_argsFunction · 0.85
iterMethod · 0.80
is_emptyMethod · 0.45

Tested by 11

context_simple_functionFunction · 0.68
context_with_prefixFunction · 0.68
context_after_positionalFunction · 0.68
context_after_named_argFunction · 0.68
context_method_callFunction · 0.68
context_static_callFunction · 0.68
context_constructorFunction · 0.68
no_context_after_arrowFunction · 0.68
context_multilineFunction · 0.68