cmakefmt/error.rs
1// SPDX-FileCopyrightText: Copyright 2026 Puneet Matharu
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5//! Structured error types returned by parsing, config loading, and formatting.
6
7use thiserror::Error;
8
9/// Structured config/spec deserialization failure metadata used for
10/// user-facing diagnostics.
11#[derive(Debug, Clone)]
12pub struct FileParseError {
13 /// Parser format name, such as `TOML` or `YAML`.
14 pub format: &'static str,
15 /// Human-readable parser message.
16 pub message: Box<str>,
17 /// Optional 1-based line number.
18 pub line: Option<usize>,
19 /// Optional 1-based column number.
20 pub column: Option<usize>,
21}
22
23/// Errors that can be returned by parsing, config loading, spec loading, or
24/// formatting operations.
25#[derive(Debug, Error)]
26pub enum Error {
27 /// A syntax error reported by the CMake parser.
28 #[error("parse error: {0}")]
29 Parse(#[from] Box<pest::error::Error<crate::parser::Rule>>),
30
31 /// A parser error annotated with source text and line-offset context.
32 #[error("parse error in {display_name}: {source}")]
33 ParseContext {
34 /// Human-facing source name, for example a path or `<stdin>`.
35 display_name: String,
36 /// The source text that failed to parse.
37 source_text: Box<str>,
38 /// The 1-based source line number where this parser chunk started.
39 start_line: usize,
40 /// Whether earlier barrier/fence handling affected how this chunk was parsed.
41 barrier_context: bool,
42 /// The underlying pest parser error.
43 source: Box<pest::error::Error<crate::parser::Rule>>,
44 },
45
46 /// A user config parse error.
47 #[error("config error in {path}: {source_message}")]
48 Config {
49 /// The config file that failed to deserialize.
50 path: std::path::PathBuf,
51 /// Structured parser details for the failure.
52 details: FileParseError,
53 /// Cached display string used by `thiserror`.
54 source_message: Box<str>,
55 },
56
57 /// A built-in or user override spec parse error.
58 #[error("spec error in {path}: {source_message}")]
59 Spec {
60 /// The spec file that failed to deserialize.
61 path: std::path::PathBuf,
62 /// Structured parser details for the failure.
63 details: FileParseError,
64 /// Cached display string used by `thiserror`.
65 source_message: Box<str>,
66 },
67
68 /// A filesystem or stream I/O failure.
69 #[error("I/O error: {0}")]
70 Io(#[from] std::io::Error),
71
72 /// A higher-level formatter or CLI error that does not fit another
73 /// structured variant.
74 #[error("formatter error: {0}")]
75 Formatter(String),
76}
77
78/// Convenience alias for crate-level results.
79pub type Result<T> = std::result::Result<T, Error>;
80
81impl Error {
82 /// Attach a human-facing source name to a contextual parser error.
83 pub fn with_display_name(self, display_name: impl Into<String>) -> Self {
84 match self {
85 Self::ParseContext {
86 source_text,
87 start_line,
88 barrier_context,
89 source,
90 ..
91 } => Self::ParseContext {
92 display_name: display_name.into(),
93 source_text,
94 start_line,
95 barrier_context,
96 source,
97 },
98 other => other,
99 }
100 }
101}