Remove a single identifier from a `@phpstan-ignore id1, id2` comment. If only one identifier remains after removal, or if the target id is the only one, falls back to removing the whole comment.
(
content: &str,
line: u32,
line_text: &str,
ignore_pos: usize,
remove_id: &str,
)
| 476 | /// If only one identifier remains after removal, or if the target id is |
| 477 | /// the only one, falls back to removing the whole comment. |
| 478 | fn build_remove_single_id( |
| 479 | content: &str, |
| 480 | line: u32, |
| 481 | line_text: &str, |
| 482 | ignore_pos: usize, |
| 483 | remove_id: &str, |
| 484 | ) -> Option<TextEdit> { |
| 485 | let ids_start = ignore_pos + "@phpstan-ignore".len(); |
| 486 | let ids_text = &line_text[ids_start..]; |
| 487 | let ids_trimmed = ids_text.trim_start(); |
| 488 | let ids_offset = ids_text.len() - ids_trimmed.len(); |
| 489 | |
| 490 | // Find where the identifier list ends. |
| 491 | let ids_end = ids_trimmed |
| 492 | .find("*/") |
| 493 | .or_else(|| ids_trimmed.find(" (")) |
| 494 | .unwrap_or(ids_trimmed.len()); |
| 495 | |
| 496 | let ids_str = ids_trimmed[..ids_end].trim(); |
| 497 | let ids: Vec<&str> = ids_str.split(',').map(|s| s.trim()).collect(); |
| 498 | |
| 499 | if ids.len() <= 1 || (ids.len() == 1 && ids[0] == remove_id) { |
| 500 | // Only one identifier (or it's the one we want to remove) — |
| 501 | // remove the whole comment. |
| 502 | return build_remove_whole_ignore(content, line, line_text, ignore_pos); |
| 503 | } |
| 504 | |
| 505 | // Check if the identifier is actually in the list. |
| 506 | if !ids.contains(&remove_id) { |
| 507 | // The identifier we're supposed to remove isn't here. |
| 508 | // Fall back to removing the whole comment. |
| 509 | return build_remove_whole_ignore(content, line, line_text, ignore_pos); |
| 510 | } |
| 511 | |
| 512 | // Remove just this identifier from the list. |
| 513 | let new_ids: Vec<&str> = ids.iter().filter(|&&id| id != remove_id).copied().collect(); |
| 514 | let new_ids_str = new_ids.join(", "); |
| 515 | |
| 516 | // Reconstruct: replace the identifier list portion. |
| 517 | let abs_ids_start = (ids_start + ids_offset) as u32; |
| 518 | let abs_ids_end = (ids_start + ids_offset + ids_end) as u32; |
| 519 | |
| 520 | Some(TextEdit { |
| 521 | range: Range { |
| 522 | start: Position { |
| 523 | line, |
| 524 | character: abs_ids_start, |
| 525 | }, |
| 526 | end: Position { |
| 527 | line, |
| 528 | character: abs_ids_end, |
| 529 | }, |
| 530 | }, |
| 531 | new_text: new_ids_str, |
| 532 | }) |
| 533 | } |
| 534 | |
| 535 | /// Parse the ignored identifier from an unmatched-ignore error message. |
no test coverage detected