Repository: astral-sh/ruff
File: crates/ruff_notebook/src/index.rs (Rust)

Code before:
impl NotebookIndex {
    pub fn new(row_to_cell: Vec<OneIndexed>, row_to_row_in_cell: Vec<OneIndexed>) -> Self {
        Self {
            row_to_cell,
            row_to_row_in_cell,
        }
    }

    /// Returns the cell number (1-based) for the given row (1-based).
    pub fn cell(&self, row: OneIndexed) -> Option<OneIndexed> {
        self.row_to_cell.get(row.to_zero_indexed()).copied()
    }

    /// Returns the row number (1-based) in the cell (1-based) for the
    /// given row (1-based).
    pub fn cell_row(&self, row: OneIndexed) -> Option<OneIndexed> {
        self.row_to_row_in_cell.get(row.to_zero_indexed()).copied()
    }

    /// Returns an iterator over the row:cell-number pairs (both 1-based).
    pub fn iter(&self) -> impl Iterator<Item = (OneIndexed, OneIndexed)> {
        self.row_to_cell
            .iter()
            .enumerate()
            .map(|(row, cell)| (OneIndexed::from_zero_indexed(row), *cell))
    }

    /// Translates the given [`LineColumn`] based on the indexing table.
    ///
    /// This will translate the row/column in the concatenated source code
    /// to the row/column in the Jupyter Notebook.
    pub fn translate_line_column(&self, source_location: &LineColumn) -> LineColumn {
        LineColumn {
            line: self
                .cell_row(source_location.line)
                .unwrap_or(OneIndexed::MIN),
            column: source_location.column,
        }
    }

    /// Translates the given [`SourceLocation`] based on the indexing table.
    ///
    /// This will translate the line/character in the concatenated source code
    /// to the line/character in the Jupyter Notebook.
    pub fn translate_source_location(&self, source_location: &SourceLocation) -> SourceLocation {
        SourceLocation {
            line: self
                .cell_row(source_location.line)
                .unwrap_or(OneIndexed::MIN),
            character_offset: source_location.character_offset,
        }

Review comment (suggestion):
```suggestion
    /// This yields one entry per Python cell (skipping over Markdown cell).
```

Code after:
impl NotebookIndex {
    fn find_cell(&self, row: OneIndexed) -> Option<CellStart> {
        match self
            .cell_starts
            .binary_search_by_key(&row, |start| start.start_row)
        {
            Ok(cell_index) => Some(self.cell_starts[cell_index]),
            Err(insertion_point) => Some(self.cell_starts[insertion_point.checked_sub(1)?]),
        }
    }

    /// Returns the (raw) cell number (1-based) for the given row (1-based).
    pub fn cell(&self, row: OneIndexed) -> Option<OneIndexed> {
        self.find_cell(row).map(|start| start.raw_cell_index)
    }

    /// Returns the row number (1-based) in the cell (1-based) for the
    /// given row (1-based).
    pub fn cell_row(&self, row: OneIndexed) -> Option<OneIndexed> {
        self.find_cell(row)
            .map(|start| OneIndexed::from_zero_indexed(row.get() - start.start_row.get()))
    }

    /// Returns an iterator over the starting rows of each cell (1-based).
    ///
    /// This yields one entry per Python cell (skipping over Makrdown cell).
    pub fn iter(&self) -> impl Iterator<Item = CellStart> + '_ {
        self.cell_starts.iter().copied()
    }

    /// Translates the given [`LineColumn`] based on the indexing table.
    ///
    /// This will translate the row/column in the concatenated source code
    /// to the row/column in the Jupyter Notebook.
    pub fn translate_line_column(&self, source_location: &LineColumn) -> LineColumn {
        LineColumn {
            line: self
                .cell_row(source_location.line)
                .unwrap_or(OneIndexed::MIN),
            column: source_location.column,
        }
    }

    /// Translates the given [`SourceLocation`] based on the indexing table.
    ///
    /// This will translate the line/character in the concatenated source code
    /// to the line/character in the Jupyter Notebook.
    pub fn translate_source_location(&self, source_location: &SourceLocation) -> SourceLocation {
        SourceLocation {
            line: self
                .cell_row(source_location.line)