Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidy up error implementations #515

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 8 additions & 19 deletions graphql_client_cli/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::fmt::{Debug, Display};

pub struct Error {
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
message: Option<String>,
Expand Down Expand Up @@ -28,25 +26,16 @@ impl Error {
}

// This is the impl that shows up when the error bubbles up to `main()`.
impl Debug for Error {
impl std::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(msg) = &self.message {
f.write_str(msg)?;
f.write_str("\n")?;
}

if self.source.is_some() && self.message.is_some() {
f.write_str("Cause: ")?;
match (&self.message, &self.source) {
(Some(msg), Some(source)) => {
write!(f, "{msg}\nCause: {source}\nLocation: {}", self.location)
}
(Some(msg), None) => write!(f, "{msg}\nLocation: {}", self.location),
(None, Some(source)) => write!(f, "{source}\nLocation: {}", self.location),
(None, None) => write!(f, "\nLocation: {}", self.location),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomhoule i've copied the original implementation here, but i suspect the leading newline here is not intentional?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. Ideally we'd have tests for the display impl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add those before this lands

}

if let Some(source) = self.source.as_ref() {
Display::fmt(source, f)?;
}

f.write_str("\nLocation: ")?;
Display::fmt(self.location, f)?;

Ok(())
}
}

Expand Down
1 change: 1 addition & 0 deletions graphql_client_codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ quote = "^1.0"
serde_json = "1.0"
serde = { version = "^1.0", features = ["derive"] }
syn = "^1.0"
thiserror = "2.0.11"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to avoid adding dependencies that are not 100% needed in this library. I like thiserror for application code, but I wouldn't use it there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you possibly confusing 'thiserror' and 'anyhow'? Thiserror targets libraries, not applications. It's a compile-time-only dependency- not exposed in public interface (it generates the boilerplate you would otherwise write by hand)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still adds to the compile times and the dependencies to audit. It's a good crate, but I wouldn't use it for a couple of modules in a library. Arguably, it's not worse than serde-derive which we already have in there, but I'm not sure why, we should remove if possible.

14 changes: 2 additions & 12 deletions graphql_client_codegen/src/generated_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@ use crate::{
use heck::*;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::{error::Error, fmt::Display};

#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
#[error("Could not find an operation named {operation_name} in the query document.")]
struct OperationNotFound {
operation_name: String,
}

impl Display for OperationNotFound {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Could not find an operation named ")?;
f.write_str(&self.operation_name)?;
f.write_str(" in the query document.")
}
}

impl Error for OperationNotFound {}

/// This struct contains the parameters necessary to generate code for a given operation.
pub(crate) struct GeneratedModule<'a> {
pub operation: &'a str,
Expand Down
53 changes: 16 additions & 37 deletions graphql_client_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,12 @@ mod tests;

pub use crate::codegen_options::{CodegenMode, GraphQLClientCodegenOptions};

use std::{collections::BTreeMap, fmt::Display, io};
use std::{collections::BTreeMap, io};

#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
#[error("{0}")]
struct GeneralError(String);

impl Display for GeneralError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}

impl std::error::Error for GeneralError {}

type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
type CacheMap<T> = std::sync::Mutex<BTreeMap<std::path::PathBuf, T>>;
type QueryDocument = graphql_parser::query::Document<'static, String>;
Expand Down Expand Up @@ -169,34 +162,20 @@ fn generate_module_token_stream_inner(
Ok(modules)
}

#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
enum ReadFileError {
FileNotFound { path: String, io_error: io::Error },
ReadError { path: String, io_error: io::Error },
}

impl Display for ReadFileError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReadFileError::FileNotFound { path, .. } => {
write!(f, "Could not find file with path: {}\n
Hint: file paths in the GraphQLQuery attribute are relative to the project root (location of the Cargo.toml). Example: query_path = \"src/my_query.graphql\".", path)
}
ReadFileError::ReadError { path, .. } => {
f.write_str("Error reading file at: ")?;
f.write_str(path)
}
}
}
}

impl std::error::Error for ReadFileError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ReadFileError::FileNotFound { io_error, .. }
| ReadFileError::ReadError { io_error, .. } => Some(io_error),
}
}
#[error("Could not find file with path: {path}\nHint: file paths in the GraphQLQuery attribute are relative to the project root (location of the Cargo.toml). Example: query_path = \"src/my_query.graphql\".")]
FileNotFound {
path: String,
#[source]
io_error: io::Error,
},
#[error("Error reading file at: {path}")]
ReadError {
path: String,
#[source]
io_error: io::Error,
},
}

fn read_file(path: &std::path::Path) -> Result<String, ReadFileError> {
Expand Down
16 changes: 3 additions & 13 deletions graphql_client_codegen/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,14 @@ use crate::{
StoredInputType, StoredScalar, TypeId, UnionId,
},
};
use std::{
collections::{BTreeMap, BTreeSet},
fmt::Display,
};
use std::collections::{BTreeMap, BTreeSet};

#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
#[error("{message}")]
pub(crate) struct QueryValidationError {
message: String,
}

impl Display for QueryValidationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.message)
}
}

impl std::error::Error for QueryValidationError {}

impl QueryValidationError {
pub(crate) fn new(message: String) -> Self {
QueryValidationError { message }
Expand Down