Skip to content

Commit

Permalink
Simpler errors
Browse files Browse the repository at this point in the history
  • Loading branch information
olivier-lacroix committed Apr 4, 2024
1 parent 98ea377 commit 24959ef
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
54 changes: 31 additions & 23 deletions src/project/manifest/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,16 @@ pub enum RequirementConversionError {
Unimplemented,
}

#[derive(Error, Debug, Clone)]
pub enum TomlError {
#[error("failed to parse project manifest")]
Error(#[from] toml_edit::TomlError),
#[error("'pyproject.toml' should contain a [project] table")]
NoProjectTable(std::ops::Range<usize>),
#[error("The [project] table should contain a 'name'")]
NoProjectName(Option<std::ops::Range<usize>>),
use std::fmt;

#[derive(Debug, Clone, Error)]
pub struct TomlError {
pub message: String,
pub span: Option<std::ops::Range<usize>>,
}

impl TomlError {
pub fn to_fancy<T>(&self, file_name: &str, contents: impl Into<String>) -> Result<T, Report> {
pub fn to_fancy<T>(self, file_name: &str, contents: impl Into<String>) -> Result<T, Report> {

Check failure on line 84 in src/project/manifest/error.rs

View workflow job for this annotation

GitHub Actions / Cargo Lint

methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
if let Some(span) = self.clone().span() {
Err(miette::miette!(
labels = vec![LabeledSpan::at(span, self.message())],
Expand All @@ -95,24 +93,34 @@ impl TomlError {
}
}

fn span(self) -> Option<std::ops::Range<usize>> {
match self {
TomlError::Error(e) => e.span(),
TomlError::NoProjectTable(span) => Some(span),
TomlError::NoProjectName(span) => span,
}
/// What went wrong
pub fn message(&self) -> &str {
&self.message
}
fn message(&self) -> &str {
match self {
TomlError::Error(e) => e.message(),
TomlError::NoProjectTable(_) => "Missing field `project`",
TomlError::NoProjectName(_) => "Missing field `name`",
}

/// The start/end index into the original document where the error occurred
pub fn span(&self) -> Option<std::ops::Range<usize>> {
self.span.clone()
}
}
impl fmt::Display for TomlError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TomlError: {} ", self.message)
}
}

impl From<toml_edit::de::Error> for TomlError {
fn from(e: toml_edit::de::Error) -> Self {
toml_edit::TomlError::from(e).into()
Self {
message: e.message().into(),
span: e.span(),
}
}
}
impl From<toml_edit::TomlError> for TomlError {
fn from(e: toml_edit::TomlError) -> Self {
Self {
message: e.message().into(),
span: e.span(),
}
}
}
5 changes: 4 additions & 1 deletion src/project/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,10 @@ impl ProjectManifest {
// Make sure project.name is defined
if manifest.project.name.is_none() {
let span = source.parse::<DocumentMut>().map_err(TomlError::from)?["project"].span();
return Err(TomlError::NoProjectName(span));
return Err(TomlError {
span,
message: String::from("missing field `name`"),
});
}

Ok(manifest)
Expand Down
7 changes: 5 additions & 2 deletions src/project/manifest/pyproject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ impl PyProjectManifest {
// This will ensure project.name is defined
// TODO: do we want to Err if tool.pixi.name is defined?
if manifest.project.is_none() {
return Err(TomlError::NoProjectTable(0..1));
return Err(TomlError {
span: Some(0..1),
message: String::from("missing field `project`"),
});
}

Ok(manifest)
Expand Down Expand Up @@ -128,7 +131,7 @@ mod tests {
const PYPROJECT_FULL: &str = r#"
[project]
name = "project"
[tool.pixi.project]
version = "0.1.0"
description = "A project"
Expand Down

0 comments on commit 24959ef

Please sign in to comment.