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

Method resolve_add_throws

src/code_actions/phpstan/add_throws.rs:162–225  ·  view source on GitHub ↗

Resolve the "Add @throws" code action by computing the full workspace edit. Phase 2**: called from [`resolve_code_action`](Self::resolve_code_action) when the user picks this action. Recomputes the docblock edit and (optionally) the import edit from the data payload.

(
        &self,
        data: &CodeActionData,
        content: &str,
    )

Source from the content-addressed store, hash-verified

160 /// picks this action. Recomputes the docblock edit and (optionally)
161 /// the import edit from the data payload.
162 pub(crate) fn resolve_add_throws(
163 &self,
164 data: &CodeActionData,
165 content: &str,
166 ) -> Option<WorkspaceEdit> {
167 let uri = &data.uri;
168
169 // Parse the extra data to recover the diagnostic message.
170 let diagnostic_message = data.extra.get("diagnostic_message")?.as_str()?;
171 let diagnostic_line = data.extra.get("diagnostic_line")?.as_u64()? as usize;
172
173 // Extract the exception FQN from the message.
174 let exception_fqn = extract_exception_fqn(diagnostic_message)?;
175 let short_name = crate::util::short_name(&exception_fqn);
176
177 // Look up the use_map and namespace_map for the URI.
178 let file_use_map: HashMap<String, String> = self.file_use_map(uri);
179 let file_namespace: Option<String> = self.first_file_namespace(uri);
180
181 // Determine if an import is needed.
182 let already_imported = file_use_map.iter().any(|(alias, fqn)| {
183 alias.eq_ignore_ascii_case(short_name) && fqn.eq_ignore_ascii_case(&exception_fqn)
184 });
185
186 let same_namespace = match &file_namespace {
187 Some(ns) => {
188 let ns_prefix = format!("{}\\", ns);
189 let stripped = exception_fqn.strip_prefix(&ns_prefix);
190 stripped.is_some_and(|rest| !rest.contains('\\'))
191 }
192 None => !exception_fqn.contains('\\'),
193 };
194
195 let needs_import = !already_imported && !same_namespace;
196
197 // Find the enclosing docblock.
198 let docblock_info = find_enclosing_docblock(content, diagnostic_line)?;
199
200 // Build edits.
201 let mut edits = Vec::new();
202
203 // 1. Docblock edit: insert @throws tag.
204 let throws_edit = build_throws_edit(content, &docblock_info, short_name);
205 edits.push(throws_edit);
206
207 // 2. Import edit (if needed).
208 if needs_import {
209 let use_block = analyze_use_block(content);
210 if let Some(import_edits) = build_use_edit(&exception_fqn, &use_block, &file_namespace)
211 {
212 edits.extend(import_edits);
213 }
214 }
215
216 let doc_uri: Url = uri.parse().ok()?;
217 let mut changes = HashMap::new();
218 changes.insert(doc_uri, edits);
219

Callers 1

resolve_code_actionMethod · 0.80

Calls 15

extract_exception_fqnFunction · 0.85
find_enclosing_docblockFunction · 0.85
build_throws_editFunction · 0.85
analyze_use_blockFunction · 0.85
build_use_editFunction · 0.85
as_strMethod · 0.80
file_use_mapMethod · 0.80
first_file_namespaceMethod · 0.80
iterMethod · 0.80
containsMethod · 0.80
pushMethod · 0.80
extendMethod · 0.80

Tested by

no test coverage detected