Skip to content

Commit b8fbda7

Browse files
committed
Leverage derive_more::Display
1 parent 34b9937 commit b8fbda7

File tree

26 files changed

+157
-308
lines changed

26 files changed

+157
-308
lines changed

book/src/types/scalars.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ For implementing [custom scalars][2] on foreign types there is [`#[graphql_scala
345345
# }
346346
#
347347
# impl std::fmt::Display for Date {
348-
# fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result {
348+
# fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
349349
# unimplemented!()
350350
# }
351351
# }

juniper/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ bson = { version = "2.4", optional = true }
5151
chrono = { version = "0.4.30", features = ["alloc"], default-features = false, optional = true }
5252
chrono-tz = { version = "0.10", default-features = false, optional = true }
5353
compact_str = "0.9"
54+
derive_more = { version = "2.0", features = ["display"] }
5455
fnv = "1.0.5"
5556
futures = { version = "0.3.22", features = ["alloc"], default-features = false }
5657
graphql-parser = { version = "0.4", optional = true }

juniper/src/integrations/jiff.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
5353
use std::{error::Error, fmt, str};
5454

55+
use derive_more::with_trait::Display;
56+
5557
use crate::{InputValue, ScalarValue, Value, graphql_scalar};
5658

5759
/// Representation of a civil date in the Gregorian calendar.
@@ -409,12 +411,13 @@ mod time_zone_or_utc_offset {
409411
}
410412

411413
/// Error parsing a [`TimeZone`] value.
412-
#[derive(Clone)]
414+
#[derive(Clone, Display)]
413415
pub enum TimeZoneParsingError {
414416
/// Identifier cannot not be parsed by the [`jiff::tz::TimeZone::get()`] method.
415417
InvalidTimeZone(jiff::Error),
416418

417419
/// GraphQL scalar [`TimeZone`] requires `tz::TimeZone` with IANA name.
420+
#[display("missing IANA name")]
418421
MissingIanaName(jiff::tz::TimeZone),
419422
}
420423

@@ -427,15 +430,6 @@ impl fmt::Debug for TimeZoneParsingError {
427430
}
428431
}
429432

430-
impl fmt::Display for TimeZoneParsingError {
431-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432-
match self {
433-
Self::InvalidTimeZone(e) => e.fmt(f),
434-
Self::MissingIanaName(..) => write!(f, "missing IANA name"),
435-
}
436-
}
437-
}
438-
439433
impl Error for TimeZoneParsingError {
440434
fn source(&self) -> Option<&(dyn Error + 'static)> {
441435
match self {
@@ -463,7 +457,8 @@ impl Error for TimeZoneParsingError {
463457
parse_token(String),
464458
specified_by_url = "https://graphql-scalars.dev/docs/scalars/time-zone",
465459
)]
466-
#[derive(Clone, Debug, Eq, PartialEq)]
460+
#[derive(Clone, Debug, Display, Eq, PartialEq)]
461+
#[display("{}", _0.iana_name().expect("failed to display `TimeZone`: no IANA name"))]
467462
pub struct TimeZone(jiff::tz::TimeZone);
468463

469464
impl TryFrom<jiff::tz::TimeZone> for TimeZone {
@@ -487,18 +482,6 @@ impl str::FromStr for TimeZone {
487482
}
488483
}
489484

490-
impl fmt::Display for TimeZone {
491-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492-
self.0
493-
.iana_name()
494-
.unwrap_or_else(|| {
495-
// PANIC: We made sure that IANA name is available when constructing `Self`.
496-
panic!("failed to display `TimeZone`: no IANA name")
497-
})
498-
.fmt(f)
499-
}
500-
}
501-
502485
impl From<TimeZone> for jiff::tz::TimeZone {
503486
fn from(value: TimeZone) -> Self {
504487
value.0

juniper/src/lib.rs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ mod for_benches_only {
1414
use bencher as _;
1515
}
1616

17-
use std::fmt;
18-
1917
// These are required by the code generated via the `juniper_codegen` macros.
2018
#[doc(hidden)]
2119
pub use {async_trait::async_trait, futures, serde, static_assertions as sa};
@@ -58,6 +56,9 @@ pub mod tests;
5856
#[cfg(test)]
5957
mod executor_tests;
6058

59+
use derive_more::with_trait::Display;
60+
use itertools::Itertools as _;
61+
6162
// Needs to be public because macros use it.
6263
pub use crate::util::to_camel_case;
6364

@@ -106,36 +107,23 @@ pub use crate::{
106107

107108
/// An error that prevented query execution
108109
#[expect(missing_docs, reason = "self-explanatory")]
109-
#[derive(Clone, Debug, Eq, PartialEq)]
110+
#[derive(Clone, Debug, Display, Eq, PartialEq)]
110111
pub enum GraphQLError {
111112
ParseError(Spanning<ParseError>),
113+
#[display("{}", _0.iter().format("\n"))]
112114
ValidationError(Vec<RuleError>),
115+
#[display("No operation provided")]
113116
NoOperationProvided,
117+
#[display("Multiple operations provided")]
114118
MultipleOperationsProvided,
119+
#[display("Unknown operation name")]
115120
UnknownOperationName,
121+
#[display("Operation is a subscription")]
116122
IsSubscription,
123+
#[display("Operation is not a subscription")]
117124
NotSubscription,
118125
}
119126

120-
impl fmt::Display for GraphQLError {
121-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122-
match self {
123-
Self::ParseError(e) => write!(f, "{e}"),
124-
Self::ValidationError(errs) => {
125-
for e in errs {
126-
writeln!(f, "{e}")?;
127-
}
128-
Ok(())
129-
}
130-
Self::NoOperationProvided => write!(f, "No operation provided"),
131-
Self::MultipleOperationsProvided => write!(f, "Multiple operations provided"),
132-
Self::UnknownOperationName => write!(f, "Unknown operation name"),
133-
Self::IsSubscription => write!(f, "Operation is a subscription"),
134-
Self::NotSubscription => write!(f, "Operation is not a subscription"),
135-
}
136-
}
137-
}
138-
139127
impl std::error::Error for GraphQLError {
140128
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
141129
match self {

juniper/src/parser/lexer.rs

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use std::{char, fmt, iter::Peekable, str::CharIndices};
1+
use std::{char, iter::Peekable, str::CharIndices};
2+
3+
use derive_more::with_trait::Display;
24

35
use crate::parser::{SourcePosition, Spanning};
46

@@ -16,76 +18,98 @@ pub struct Lexer<'a> {
1618
///
1719
/// This is only used for tagging how the lexer has interpreted a value literal
1820
#[expect(missing_docs, reason = "self-explanatory")]
19-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
21+
#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)]
2022
pub enum ScalarToken<'a> {
23+
#[display("\"{}\"", _0.replace('\\', "\\\\").replace('"', "\\\""))]
2124
String(&'a str),
2225
Float(&'a str),
2326
Int(&'a str),
2427
}
2528

2629
/// A single token in the input source
2730
#[expect(missing_docs, reason = "self-explanatory")]
28-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31+
#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)]
2932
pub enum Token<'a> {
3033
Name(&'a str),
3134
Scalar(ScalarToken<'a>),
35+
#[display("!")]
3236
ExclamationMark,
37+
#[display("$")]
3338
Dollar,
39+
#[display("(")]
3440
ParenOpen,
41+
#[display(")")]
3542
ParenClose,
43+
#[display("[")]
3644
BracketOpen,
45+
#[display("]")]
3746
BracketClose,
47+
#[display("{{")]
3848
CurlyOpen,
49+
#[display("}}")]
3950
CurlyClose,
51+
#[display("...")]
4052
Ellipsis,
53+
#[display(":")]
4154
Colon,
55+
#[display("=")]
4256
Equals,
57+
#[display("@")]
4358
At,
59+
#[display("|")]
4460
Pipe,
61+
#[display("End of file")]
4562
EndOfFile,
4663
}
4764

4865
/// Error when tokenizing the input source
49-
#[derive(Clone, Debug, PartialEq, Eq)]
66+
#[derive(Clone, Debug, Display, Eq, PartialEq)]
5067
pub enum LexerError {
5168
/// An unknown character was found
5269
///
5370
/// Unknown characters are characters that do not occur anywhere in the
5471
/// GraphQL language, such as `?` or `%`.
72+
#[display("Unknown character \"{_0}\"")]
5573
UnknownCharacter(char),
5674

5775
/// An unexpected character was found
5876
///
5977
/// Unexpected characters are characters that _do_ exist in the GraphQL
6078
/// language, but is not expected at the current position in the document.
79+
#[display("Unexpected character \"{_0}\"")]
6180
UnexpectedCharacter(char),
6281

6382
/// An unterminated string literal was found
6483
///
6584
/// Apart from forgetting the ending `"`, terminating a string within a
6685
/// Unicode escape sequence or having a line break in the string also
6786
/// causes this error.
87+
#[display("Unterminated string literal")]
6888
UnterminatedString,
6989

7090
/// An unknown character in a string literal was found
7191
///
7292
/// This occurs when an invalid source character is found in a string
7393
/// literal, such as ASCII control characters.
94+
#[display("Unknown character \"{_0}\" in string literal")]
7495
UnknownCharacterInString(char),
7596

7697
/// An unknown escape sequence in a string literal was found
7798
///
7899
/// Only a limited set of escape sequences are supported, this is emitted
79100
/// when e.g. `"\l"` is parsed.
101+
#[display("Unknown escape sequence \"{_0}\" in string")]
80102
UnknownEscapeSequence(String),
81103

82104
/// The input source was unexpectedly terminated
83105
///
84106
/// Emitted when the current token requires a succeeding character, but
85107
/// the source has reached EOF. Emitted when scanning e.g. `"1."`.
108+
#[display("Unexpected end of input")]
86109
UnexpectedEndOfFile,
87110

88111
/// An invalid number literal was found
112+
#[display("Invalid number literal")]
89113
InvalidNumber,
90114
}
91115

@@ -477,34 +501,6 @@ impl<'a> Iterator for Lexer<'a> {
477501
}
478502
}
479503

480-
impl fmt::Display for Token<'_> {
481-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482-
match *self {
483-
Token::Name(name) => write!(f, "{name}"),
484-
Token::Scalar(ScalarToken::Int(s)) | Token::Scalar(ScalarToken::Float(s)) => {
485-
write!(f, "{s}")
486-
}
487-
Token::Scalar(ScalarToken::String(s)) => {
488-
write!(f, "\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
489-
}
490-
Token::ExclamationMark => write!(f, "!"),
491-
Token::Dollar => write!(f, "$"),
492-
Token::ParenOpen => write!(f, "("),
493-
Token::ParenClose => write!(f, ")"),
494-
Token::BracketOpen => write!(f, "["),
495-
Token::BracketClose => write!(f, "]"),
496-
Token::CurlyOpen => write!(f, "{{"),
497-
Token::CurlyClose => write!(f, "}}"),
498-
Token::Ellipsis => write!(f, "..."),
499-
Token::Colon => write!(f, ":"),
500-
Token::Equals => write!(f, "="),
501-
Token::At => write!(f, "@"),
502-
Token::Pipe => write!(f, "|"),
503-
Token::EndOfFile => write!(f, "End of file"),
504-
}
505-
}
506-
}
507-
508504
fn is_source_char(c: char) -> bool {
509505
c == '\t' || c == '\n' || c == '\r' || c >= ' '
510506
}
@@ -521,22 +517,4 @@ fn is_number_start(c: char) -> bool {
521517
c == '-' || c.is_ascii_digit()
522518
}
523519

524-
impl fmt::Display for LexerError {
525-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526-
match *self {
527-
LexerError::UnknownCharacter(c) => write!(f, "Unknown character \"{c}\""),
528-
LexerError::UnterminatedString => write!(f, "Unterminated string literal"),
529-
LexerError::UnknownCharacterInString(c) => {
530-
write!(f, "Unknown character \"{c}\" in string literal")
531-
}
532-
LexerError::UnknownEscapeSequence(ref s) => {
533-
write!(f, "Unknown escape sequence \"{s}\" in string")
534-
}
535-
LexerError::UnexpectedCharacter(c) => write!(f, "Unexpected character \"{c}\""),
536-
LexerError::UnexpectedEndOfFile => write!(f, "Unexpected end of input"),
537-
LexerError::InvalidNumber => write!(f, "Invalid number literal"),
538-
}
539-
}
540-
}
541-
542520
impl std::error::Error for LexerError {}

juniper/src/parser/parser.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
use std::{error::Error, fmt};
22

33
use compact_str::{CompactString, format_compact};
4+
use derive_more::with_trait::Display;
45

56
use crate::parser::{Lexer, LexerError, Spanning, Token};
67

78
/// Error while parsing a GraphQL query
8-
#[derive(Clone, Debug, Eq, PartialEq)]
9+
#[derive(Clone, Debug, Display, Eq, PartialEq)]
910
pub enum ParseError {
1011
/// An unexpected token occurred in the source
1112
// TODO: Previously was `Token<'a>`.
1213
// Revisit on `graphql-parser` integration.
14+
#[display("Unexpected \"{_0}\"")]
1315
UnexpectedToken(CompactString),
1416

1517
/// The input source abruptly ended
18+
#[display("Unexpected end of input")]
1619
UnexpectedEndOfFile,
1720

1821
/// An error during tokenization occurred
@@ -22,17 +25,6 @@ pub enum ParseError {
2225
ExpectedScalarError(&'static str),
2326
}
2427

25-
impl fmt::Display for ParseError {
26-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27-
match self {
28-
Self::UnexpectedToken(token) => write!(f, "Unexpected \"{token}\""),
29-
Self::UnexpectedEndOfFile => write!(f, "Unexpected end of input"),
30-
Self::LexerError(e) => e.fmt(f),
31-
Self::ExpectedScalarError(e) => e.fmt(f),
32-
}
33-
}
34-
}
35-
3628
impl Error for ParseError {
3729
fn source(&self) -> Option<&(dyn Error + 'static)> {
3830
match self {

juniper/src/parser/utils.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::fmt;
22

3+
use derive_more::with_trait::Display;
4+
35
/// A reference to a line and column in an input source file
4-
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
6+
#[derive(Clone, Copy, Debug, Display, Eq, Hash, Ord, PartialEq, PartialOrd)]
7+
#[display("{line}:{col}")]
58
pub struct SourcePosition {
69
index: usize,
710
line: usize,
@@ -136,8 +139,8 @@ impl<T> Spanning<T, Span> {
136139
}
137140
}
138141

139-
impl<T: fmt::Display> fmt::Display for Spanning<T> {
140-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142+
impl<T: Display> Display for Spanning<T> {
143+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141144
write!(f, "{}. At {}", self.item, self.span.start)
142145
}
143146
}
@@ -196,9 +199,3 @@ impl SourcePosition {
196199
self.col
197200
}
198201
}
199-
200-
impl fmt::Display for SourcePosition {
201-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202-
write!(f, "{}:{}", self.line, self.col)
203-
}
204-
}

0 commit comments

Comments
 (0)