Compute selection ranges for the given positions in the file.
(
&self,
content: &str,
positions: &[Position],
)
| 23 | impl Backend { |
| 24 | /// Compute selection ranges for the given positions in the file. |
| 25 | pub fn handle_selection_range( |
| 26 | &self, |
| 27 | content: &str, |
| 28 | positions: &[Position], |
| 29 | ) -> Option<Vec<SelectionRange>> { |
| 30 | let arena = Bump::new(); |
| 31 | let file_id = mago_database::file::FileId::new("input.php"); |
| 32 | let program = mago_syntax::parser::parse_file_content(&arena, file_id, content); |
| 33 | |
| 34 | let mut results = Vec::with_capacity(positions.len()); |
| 35 | |
| 36 | for pos in positions { |
| 37 | let offset = position_to_offset(content, *pos); |
| 38 | |
| 39 | // Collect all spans that contain the cursor, from the AST walk. |
| 40 | let mut spans: Vec<(u32, u32)> = Vec::new(); |
| 41 | |
| 42 | // Add the whole-file span as the outermost range. |
| 43 | let file_span = (0u32, content.len() as u32); |
| 44 | spans.push(file_span); |
| 45 | |
| 46 | for stmt in program.statements.iter() { |
| 47 | collect_spans_from_statement(stmt, offset, &mut spans); |
| 48 | } |
| 49 | |
| 50 | // Deduplicate identical spans and sort outermost-first (largest |
| 51 | // span first). When two spans have the same length, the one |
| 52 | // starting earlier comes first. |
| 53 | spans.sort_unstable(); |
| 54 | spans.dedup(); |
| 55 | spans.sort_by(|a, b| { |
| 56 | let len_a = a.1.saturating_sub(a.0); |
| 57 | let len_b = b.1.saturating_sub(b.0); |
| 58 | len_b.cmp(&len_a).then(a.0.cmp(&b.0)) |
| 59 | }); |
| 60 | |
| 61 | // Build the linked list from outermost to innermost. |
| 62 | let selection_range = build_selection_range(content, &spans); |
| 63 | results.push(selection_range); |
| 64 | } |
| 65 | |
| 66 | Some(results) |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | // ─── Linked-list builder ──────────────────────────────────────────────────── |
no test coverage detected