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,
)
| 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 |
no test coverage detected