## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/common/src/diagnostic.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    use crate::Span;
    19
    20
    /// Additional contextual information intended for end users, to help them
    21
    /// understand what went wrong by providing human-readable messages, and
    22
    /// locations in the source query that relate to the error in some way.
    23
    ///
    24
    /// You can think of a single [`Diagnostic`] as a single "block" of output from
    25
    /// rustc. i.e. either an error or a warning, optionally with some notes and
    26
    /// help messages.
    27
    ///
    28
    /// Example:
    29
    ///
    30
    /// ```rust
    31
    /// # use datafusion_common::{Location, Span, Diagnostic};
    32
    /// let span = Some(Span {
    33
    ///     start: Location { line: 2, column: 1 },
    34
    ///     end: Location {
    35
    ///         line: 4,
    36
    ///         column: 15,
    37
    ///     },
    38
    /// });
    39
    /// let diagnostic = Diagnostic::new_error("Something went wrong", span)
    40
    ///     .with_help("Have you tried turning it on and off again?", None);
    41
    /// ```
    42
    #[derive(Debug, Clone)]
    43
    pub struct Diagnostic {
    44
        pub kind: DiagnosticKind,
    45
        pub message: String,
    46
        pub span: Option<Span>,
    47
        pub notes: Vec<DiagnosticNote>,
    48
        pub helps: Vec<DiagnosticHelp>,
    49
    }
    50
    51
    /// A note enriches a [`Diagnostic`] with extra information, possibly referring
    52
    /// to different locations in the original SQL query, that helps contextualize
    53
    /// the error and helps the end user understand why it occurred.
    54
    ///
    55
    /// Example:
    56
    /// SELECT id, name FROM users GROUP BY id
    57
    /// Note:      ^^^^ 'name' is not in the GROUP BY clause
    58
    #[derive(Debug, Clone)]
    59
    pub struct DiagnosticNote {
    60
        pub message: String,
    61
        pub span: Option<Span>,
    62
    }
    63
    64
    /// A "help" enriches a [`Diagnostic`] with extra information, possibly
    65
    /// referring to different locations in the original SQL query, that helps the
    66
    /// user understand how they might fix the error or warning.
    67
    ///
    68
    /// Example:
    69
    /// SELECT id, name FROM users GROUP BY id
    70
    /// Help: Add 'name' here                 ^^^^
    71
    #[derive(Debug, Clone)]
    72
    pub struct DiagnosticHelp {
    73
        pub message: String,
    74
        pub span: Option<Span>,
    75
    }
    76
    77
    /// A [`Diagnostic`] can either be a hard error that prevents the query from
    78
    /// being planned and executed, or a warning that indicates potential issues,
    79
    /// performance problems, or causes for unexpected results, but is non-fatal.
    80
    /// This enum expresses these two possibilities.
    81
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    82
    pub enum DiagnosticKind {
    83
        Error,
    84
        Warning,
    85
    }
    86
    87
    impl Diagnostic {
    88
        /// Creates a new [`Diagnostic`] for a fatal error that prevents the SQL
    89
        /// query from being planned and executed. Optionally takes in a [`Span`] to
    90
        /// describe the location in the source code that caused the error, should
    91
        /// be provided when available.
    92
    0
        pub fn new_error(message: impl Into<String>, span: Option<Span>) -> Self {
    93
    0
            Self {
    94
    0
                kind: DiagnosticKind::Error,
    95
    0
                message: message.into(),
    96
    0
                span,
    97
    0
                notes: Vec::new(),
    98
    0
                helps: Vec::new(),
    99
    0
            }
    100
    0
        }
    101
    102
        /// Creates a new [`Diagnostic`] for a NON-fatal warning, such as a
    103
        /// performance problem, or possible cause for undesired results. Optionally
    104
        /// takes in a [`Span`] to describe the location in the source code that
    105
        /// caused the error, should be provided when available.
    106
    0
        pub fn new_warning(message: impl Into<String>, span: Option<Span>) -> Self {
    107
    0
            Self {
    108
    0
                kind: DiagnosticKind::Warning,
    109
    0
                message: message.into(),
    110
    0
                span,
    111
    0
                notes: Vec::new(),
    112
    0
                helps: Vec::new(),
    113
    0
            }
    114
    0
        }
    115
    116
        /// Adds a "note" to the [`Diagnostic`], which can have zero or many. A "note"
    117
        /// helps contextualize the error and helps the end user understand why it
    118
        /// occurred. It can refer to an arbitrary location in the SQL query, or to
    119
        /// no location.
    120
    0
        pub fn add_note(&mut self, message: impl Into<String>, span: Option<Span>) {
    121
    0
            self.notes.push(DiagnosticNote {
    122
    0
                message: message.into(),
    123
    0
                span,
    124
    0
            });
    125
    0
        }
    126
    127
        /// Adds a "help" to the [`Diagnostic`], which can have zero or many. A
    128
        /// "help" helps the user understand how they might fix the error or
    129
        /// warning. It can refer to an arbitrary location in the SQL query, or to
    130
        /// no location.
    131
    0
        pub fn add_help(&mut self, message: impl Into<String>, span: Option<Span>) {
    132
    0
            self.helps.push(DiagnosticHelp {
    133
    0
                message: message.into(),
    134
    0
                span,
    135
    0
            });
    136
    0
        }
    137
    138
        /// Like [`Diagnostic::add_note`], but returns `self` to allow chaining.
    139
    0
        pub fn with_note(mut self, message: impl Into<String>, span: Option<Span>) -> Self {
    140
    0
            self.add_note(message.into(), span);
    141
    0
            self
    142
    0
        }
    143
    144
        /// Like [`Diagnostic::add_help`], but returns `self` to allow chaining.
    145
    0
        pub fn with_help(mut self, message: impl Into<String>, span: Option<Span>) -> Self {
    146
    0
            self.add_help(message.into(), span);
    147
    0
            self
    148
    0
        }
    149
    }