Repository: helix-editor/helix
File: helix-term/src/ui/text_decorations/diagnostics.rs (Rust)

Code before:
    config: &'a InlineDiagnosticsConfig,
    styles: &'a Styles,
}

impl Renderer<'_, '_> {
    fn draw_decoration(&mut self, g: &'static str, severity: Severity, col: u16) {
        self.draw_decoration_at(g, severity, col, self.row)
    }

    fn draw_decoration_at(&mut self, g: &'static str, severity: Severity, col: u16, row: u16) {
        self.renderer.draw_decoration_grapheme(
            Grapheme::new_decoration(g),
            self.styles.severity_style(severity),
            row,
            col,
        );
    }

    fn draw_eol_diagnostic(&mut self, diag: &Diagnostic, row: u16, col: usize) -> u16 {
        let style = self.styles.severity_style(diag.severity());
        let width = self.renderer.viewport.width;
        if !self.renderer.column_in_bounds(col + 1, 1) {
            return 0;
        }
        let col = (col - self.renderer.offset.col) as u16;
        let message = diag.message.replace('\n', "  ");
        let (new_col, _) = self.renderer.set_string_truncated(
            self.renderer.viewport.x + col + 1,
            row,
            &message,
            width.saturating_sub(col + 1) as usize,
            |_| style,
            true,
            false,
        );
        new_col - col
    }

    fn draw_diagnostic(&mut self, diag: &Diagnostic, col: u16, next_severity: Option<Severity>) {
        let severity = diag.severity();
        let (sym, sym_severity) = if let Some(next_severity) = next_severity {
            (STACK, next_severity.max(severity))
        } else {
            (BR_CORNER, severity)
        };
        self.draw_decoration(sym, sym_severity, col);
        for i in 0..self.config.prefix_len {
            self.draw_decoration(HOR_BAR, severity, col + i + 1);
        }

        let text_col = col + self.config.prefix_len + 1;

Review comment (refactor):
this allocates a lot (once for each diagnostic during each frame). I intentionally didn't do something like this in the original PR for this reason. We will need to refactor `set_string_truncated` but since there are other consumers that is a larger change and I am worried about breaking other places that use that API (but maybe after this change we can update unicode-width and then it's fine?)

Code after:
    config: &'a InlineDiagnosticsConfig,
    styles: &'a Styles,
}

impl Renderer<'_, '_> {
    fn draw_decoration(&mut self, g: &'static str, severity: Severity, col: u16) {
        self.draw_decoration_at(g, severity, col, self.row)
    }

    fn draw_decoration_at(&mut self, g: &'static str, severity: Severity, col: u16, row: u16) {
        self.renderer.draw_decoration_grapheme(
            Grapheme::new_decoration(g),
            self.styles.severity_style(severity),
            row,
            col,
        );
    }

    fn draw_eol_diagnostic(&mut self, diag: &Diagnostic, row: u16, col: usize) -> u16 {
        let style = self.styles.severity_style(diag.severity());
        let width = self.renderer.viewport.width;
        let start_col = (col - self.renderer.offset.col) as u16;
        let mut end_col = start_col;
        let mut draw_col = (col + 1) as u16;

        for line in diag.message.lines() {
            if !self.renderer.column_in_bounds(draw_col as usize, 1) {
                break;
            }

            (end_col, _) = self.renderer.set_string_truncated(
                self.renderer.viewport.x + draw_col,
                row,
                line,
                width.saturating_sub(draw_col) as usize,
                |_| style,
                true,
                false,
            );

            draw_col = end_col - self.renderer.viewport.x + 2; // double space between lines
        }

        end_col - start_col
    }

    fn draw_diagnostic(&mut self, diag: &Diagnostic, col: u16, next_severity: Option<Severity>) {
        let severity = diag.severity();
        let (sym, sym_severity) = if let Some(next_severity) = next_severity {
            (STACK, next_severity.max(severity))
        } else {