#![allow(unused_assignments)] // Fields are used by derive macros (miette, thiserror).

use crate::Location;
use miette::{Diagnostic, NamedSource, SourceSpan};
use thiserror::Error;

/// Interpreter warning.
#[derive(Clone, Debug, Error, Diagnostic)]
#[error("{kind}")]
#[diagnostic(severity(Warning))]
pub struct InterpretWarning {
    #[source_code]
    source_code: NamedSource<String>,

    #[label("{kind}")]
    span: SourceSpan,

    kind: InterpretWarningKind,

    #[help]
    help: Option<String>,
}

/// Interpret warning kind.
#[derive(Clone, Debug, Diagnostic, Error)]
pub enum InterpretWarningKind {
    #[error("Unused value")]
    UnusedValue,
}

impl InterpretWarning {
    /// Return the warning kind.
    #[must_use]
    pub fn kind(&self) -> &InterpretWarningKind {
        &self.kind
    }

    /// Create a new interpret warning.
    #[must_use]
    pub fn new(
        source_code: NamedSource<String>,
        loc: &Location,
        kind: InterpretWarningKind,
        help: Option<impl Into<String>>,
        length: Option<usize>,
    ) -> Self {
        let span = (
            loc.as_source_offset(source_code.inner()),
            length.unwrap_or(1),
        );
        Self {
            source_code,
            span: span.into(),
            kind,
            help: help.map(Into::into),
        }
    }
}
