shorten dbg-pls to 16 lines

This commit is contained in:
nora 2022-04-23 23:39:53 +02:00
parent 1ec9a9df34
commit 6ca7ab5734
13 changed files with 4 additions and 973 deletions

54
Cargo.lock generated
View file

@ -5,13 +5,6 @@ version = 3
[[package]]
name = "dbg-pls"
version = "0.2.2"
dependencies = [
"itoa",
"proc-macro2",
"quote",
"ryu",
"syn",
]
[[package]]
name = "dilaria"
@ -19,50 +12,3 @@ version = "0.1.0"
dependencies = [
"dbg-pls",
]
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "proc-macro2"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "syn"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"

View file

@ -7,19 +7,3 @@ description = "Syntax aware pretty-printing debugging"
license = "MIT"
repository = "https://github.com/conradludgate/dbg-pls"
readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = { version = "1", features = ["full"] }
proc-macro2 = "1"
quote = "1"
itoa = "1"
ryu = "1"
[features]
default = []
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View file

@ -1,69 +0,0 @@
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for list-like structures.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
///
/// struct Foo(Vec<i32>);
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter<'_>) {
/// f.debug_list().entries(&self.0).finish()
/// }
/// }
///
/// let value = Foo(vec![10, 11]);
/// assert_eq!(format!("{}", pretty(&value)), "[10, 11]");
/// ```
pub struct DebugList<'a> {
formatter: Formatter<'a>,
expr: syn::ExprArray,
}
impl<'a> DebugList<'a> {
pub(crate) fn new(formatter: Formatter<'a>) -> Self {
DebugList {
formatter,
expr: syn::ExprArray {
attrs: vec![],
bracket_token: syn::token::Bracket::default(),
elems: syn::punctuated::Punctuated::default(),
},
}
}
/// Adds a new entry to the list output.
#[must_use]
pub fn entry(mut self, entry: &dyn DebugPls) -> Self {
self.expr.elems.push(Formatter::process(entry));
self
}
/// Adds all the entries to the list output.
#[must_use]
pub fn entries<D, I>(mut self, entries: I) -> Self
where
D: DebugPls,
I: IntoIterator<Item = D>,
{
self.extend(entries);
self
}
/// Closes off the list
pub fn finish(self) {
self.formatter.write_expr(self.expr);
}
}
impl<'f, D: DebugPls> Extend<D> for DebugList<'f> {
fn extend<T: IntoIterator<Item = D>>(&mut self, iter: T) {
self.expr
.elems
.extend(iter.into_iter().map(|entry| Formatter::process(&entry)));
}
}

View file

@ -1,126 +0,0 @@
use std::iter::FromIterator;
use syn::punctuated::Punctuated;
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for maps.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
/// use std::collections::BTreeMap;
///
/// struct Foo(BTreeMap<String, i32>);
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter) {
/// f.debug_map().entries(&self.0).finish()
/// }
/// }
/// let mut value = Foo(BTreeMap::from([
/// ("Hello".to_string(), 5),
/// ("World".to_string(), 10),
/// ]));
/// assert_eq!(
/// format!("{}", pretty(&value)),
/// "{
/// [\"Hello\"] = 5;
/// [\"World\"] = 10;
/// }",
/// );
/// ```
pub struct DebugMap<'a> {
formatter: Formatter<'a>,
set: syn::Block,
key: Option<syn::Expr>,
}
impl<'a> DebugMap<'a> {
pub(crate) fn new(formatter: Formatter<'a>) -> Self {
DebugMap {
formatter,
set: syn::Block {
brace_token: syn::token::Brace::default(),
stmts: vec![],
},
key: None,
}
}
/// Adds the key part to the map output.
///
/// # Panics
///
/// `key` must be called before `value` and each call to `key` must be followed
/// by a corresponding call to `value`. Otherwise this method will panic.
#[must_use]
pub fn key(mut self, key: &dyn DebugPls) -> Self {
if self.key.replace(Formatter::process(key)).is_some() {
panic!("attempted to begin a new map entry without completing the previous one");
}
self
}
/// Adds the value part to the map output.
///
/// # Panics
///
/// `key` must be called before `value` and each call to `key` must be followed
/// by a corresponding call to `value`. Otherwise this method will panic.
#[must_use]
pub fn value(mut self, value: &dyn DebugPls) -> Self {
let key = self
.key
.take()
.expect("attempted to format a map value before its key");
let value = Formatter::process(value);
let entry = syn::ExprAssign {
attrs: vec![],
left: Box::new(
syn::ExprArray {
attrs: vec![],
bracket_token: syn::token::Bracket::default(),
elems: Punctuated::from_iter([key]),
}
.into(),
),
eq_token: syn::token::Eq::default(),
right: Box::new(value),
};
self.set
.stmts
.push(syn::Stmt::Semi(entry.into(), syn::token::Semi::default()));
self
}
/// Adds the entry to the map output.
#[must_use]
pub fn entry(self, key: &dyn DebugPls, value: &dyn DebugPls) -> Self {
self.key(key).value(value)
}
/// Adds all the entries to the map output.
#[must_use]
pub fn entries<K, V, I>(self, entries: I) -> Self
where
K: DebugPls,
V: DebugPls,
I: IntoIterator<Item = (K, V)>,
{
entries
.into_iter()
.fold(self, |f, (key, value)| f.entry(&key, &value))
}
/// Closes off the map.
pub fn finish(self) {
self.formatter.write_expr(syn::ExprBlock {
attrs: vec![],
label: None,
block: self.set,
});
}
}

View file

@ -1,80 +0,0 @@
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for sets.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
/// use std::collections::BTreeSet;
///
/// struct Foo(BTreeSet<String>);
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter) {
/// f.debug_set().entries(&self.0).finish()
/// }
/// }
/// let mut value = Foo(BTreeSet::from([
/// "Hello".to_string(),
/// "World".to_string(),
/// ]));
/// assert_eq!(
/// format!("{}", pretty(&value)),
/// "{
/// \"Hello\";
/// \"World\"
/// }",
/// );
/// ```
pub struct DebugSet<'a> {
formatter: Formatter<'a>,
set: syn::Block,
}
impl<'a> DebugSet<'a> {
pub(crate) fn new(formatter: Formatter<'a>) -> Self {
DebugSet {
formatter,
set: syn::Block {
brace_token: syn::token::Brace::default(),
stmts: vec![],
},
}
}
/// Adds the entry to the set output.
#[must_use]
pub fn entry(mut self, value: &dyn DebugPls) -> Self {
let expr = Formatter::process(value);
self.set
.stmts
.push(syn::Stmt::Semi(expr, syn::token::Semi::default()));
self
}
/// Adds all the entries to the set output.
#[must_use]
pub fn entries<V, I>(self, entries: I) -> Self
where
V: DebugPls,
I: IntoIterator<Item = V>,
{
entries.into_iter().fold(self, |f, entry| f.entry(&entry))
}
/// Closes off the set.
pub fn finish(mut self) {
// remove the last semicolon
if let Some(syn::Stmt::Semi(entry, _)) = self.set.stmts.pop() {
self.set.stmts.push(syn::Stmt::Expr(entry));
}
self.formatter.write_expr(syn::ExprBlock {
attrs: vec![],
label: None,
block: self.set,
});
}
}

View file

@ -1,77 +0,0 @@
use syn::__private::Span;
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for structs.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
///
/// struct Foo {
/// bar: i32,
/// baz: String,
/// }
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter) {
/// f.debug_struct("Foo")
/// .field("bar", &self.bar)
/// .field("baz", &self.baz)
/// .finish()
/// }
/// }
/// let value = Foo {
/// bar: 10,
/// baz: "Hello World".to_string(),
/// };
/// assert_eq!(
/// format!("{}", pretty(&value)),
/// "Foo { bar: 10, baz: \"Hello World\" }",
/// );
/// ```
pub struct DebugStruct<'a> {
formatter: Formatter<'a>,
expr: syn::ExprStruct,
}
impl<'a> DebugStruct<'a> {
pub(crate) fn new(formatter: Formatter<'a>, name: &str) -> Self {
DebugStruct {
formatter,
expr: syn::ExprStruct {
attrs: vec![],
path: syn::Ident::new(name, Span::call_site()).into(),
brace_token: syn::token::Brace::default(),
fields: syn::punctuated::Punctuated::new(),
dot2_token: None,
rest: None,
},
}
}
/// Adds the field to the struct output.
#[must_use]
pub fn field(mut self, name: &str, value: &dyn DebugPls) -> Self {
self.expr.fields.push(syn::FieldValue {
expr: Formatter::process(value),
attrs: vec![],
member: syn::Member::Named(syn::Ident::new(name, Span::call_site())),
colon_token: Some(syn::token::Colon::default()),
});
self
}
/// Closes off the struct.
pub fn finish(self) {
self.formatter.write_expr(self.expr);
}
/// Closes off the struct with `..`.
pub fn finish_non_exhaustive(mut self) {
self.expr.dot2_token = Some(syn::token::Dot2::default());
self.finish();
}
}

View file

@ -1,53 +0,0 @@
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for tuples.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
///
/// struct Foo(i32, String);
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter) {
/// f.debug_tuple()
/// .field(&self.0)
/// .field(&self.1)
/// .finish()
/// }
/// }
///
/// let value = Foo(10, "Hello".to_string());
/// assert_eq!(format!("{}", pretty(&value)), "(10, \"Hello\")");
/// ```
pub struct DebugTuple<'a> {
formatter: Formatter<'a>,
expr: syn::ExprTuple,
}
impl<'a> DebugTuple<'a> {
pub(crate) fn new(formatter: Formatter<'a>) -> Self {
DebugTuple {
formatter,
expr: syn::ExprTuple {
attrs: vec![],
paren_token: syn::token::Paren::default(),
elems: syn::punctuated::Punctuated::new(),
},
}
}
/// Adds the field to the tuple output.
#[must_use]
pub fn field(mut self, value: &dyn DebugPls) -> Self {
self.expr.elems.push(Formatter::process(value));
self
}
/// Closes off the tuple.
pub fn finish(self) {
self.formatter.write_expr(self.expr);
}
}

View file

@ -1,60 +0,0 @@
use syn::__private::Span;
use crate::{DebugPls, Formatter};
/// A helper designed to assist with creation of
/// [`DebugPls`] implementations for tuple structs.
///
/// # Examples
///
/// ```rust
/// use dbg_pls::{pretty, DebugPls, Formatter};
///
/// struct Foo(i32, String);
///
/// impl DebugPls for Foo {
/// fn fmt(&self, f: Formatter) {
/// f.debug_tuple_struct("Foo")
/// .field(&self.0)
/// .field(&self.1)
/// .finish()
/// }
/// }
///
/// let value = Foo(10, "Hello".to_string());
/// assert_eq!(format!("{}", pretty(&value)), "Foo(10, \"Hello\")");
/// ```
pub struct DebugTupleStruct<'a> {
formatter: Formatter<'a>,
expr: syn::ExprCall,
}
impl<'a> DebugTupleStruct<'a> {
pub(crate) fn new(formatter: Formatter<'a>, name: &str) -> Self {
DebugTupleStruct {
formatter,
expr: syn::ExprCall {
attrs: vec![],
func: Box::new(syn::Expr::Path(syn::ExprPath {
attrs: vec![],
qself: None,
path: syn::Ident::new(name, Span::call_site()).into(),
})),
paren_token: syn::token::Paren::default(),
args: syn::punctuated::Punctuated::new(),
},
}
}
/// Adds the field to the tuple struct output.
#[must_use]
pub fn field(mut self, value: &dyn DebugPls) -> Self {
self.expr.args.push(Formatter::process(value));
self
}
/// Closes off the tuple struct.
pub fn finish(self) {
self.formatter.write_expr(self.expr);
}
}

View file

@ -1,2 +0,0 @@
mod std;
mod syn_impls;

View file

@ -1,162 +0,0 @@
mod collections;
use std::{
ops::ControlFlow,
rc::Rc,
sync::{Arc, Mutex, MutexGuard, TryLockError},
task::Poll,
};
use crate::{DebugPls, Formatter};
use syn::__private::Span;
impl<T: ?Sized + DebugPls> DebugPls for Box<T> {
fn fmt(&self, f: Formatter<'_>) {
DebugPls::fmt(&**self, f);
}
}
impl<'a, D: DebugPls + ?Sized> DebugPls for &'a D {
fn fmt(&self, f: Formatter<'_>) {
D::fmt(self, f);
}
}
impl<T: ?Sized + DebugPls> DebugPls for Rc<T> {
fn fmt(&self, f: Formatter<'_>) {
DebugPls::fmt(&**self, f);
}
}
impl<T: ?Sized + DebugPls> DebugPls for Arc<T> {
fn fmt(&self, f: Formatter<'_>) {
DebugPls::fmt(&**self, f);
}
}
impl<T: ?Sized + DebugPls> DebugPls for MutexGuard<'_, T> {
fn fmt(&self, f: Formatter<'_>) {
DebugPls::fmt(&**self, f);
}
}
impl<T: ?Sized + DebugPls> DebugPls for Mutex<T> {
fn fmt(&self, f: Formatter<'_>) {
let d = f.debug_struct("Mutex");
match self.try_lock() {
Ok(guard) => d.field("data", &&*guard),
Err(TryLockError::Poisoned(err)) => d.field("data", &&**err.get_ref()),
Err(TryLockError::WouldBlock) => d.field("data", &"<locked>"),
}
.field("poisoned", &self.is_poisoned())
.finish_non_exhaustive();
}
}
macro_rules! debug_integers {
($($T:ident)*) => {$(
impl DebugPls for $T {
fn fmt(&self, f: Formatter<'_>) {
let mut buf = itoa::Buffer::new();
f.write_expr(syn::ExprLit {
attrs: vec![],
lit: syn::LitInt::new(buf.format(*self), Span::call_site()).into(),
});
}
}
)*};
}
debug_integers! {
i8 i16 i32 i64 i128 isize
u8 u16 u32 u64 u128 usize
}
macro_rules! debug_floats {
($ty:ident) => {
impl DebugPls for $ty {
fn fmt(&self, f: Formatter<'_>) {
let mut buf = ryu::Buffer::new();
f.write_expr(syn::ExprLit {
attrs: vec![],
lit: syn::LitFloat::new(buf.format(*self), Span::call_site()).into(),
});
}
}
};
}
debug_floats! { f32 }
debug_floats! { f64 }
impl DebugPls for bool {
fn fmt(&self, f: Formatter<'_>) {
match self {
true => f.debug_ident("true"),
false => f.debug_ident("false"),
}
}
}
impl<D: DebugPls> DebugPls for [D] {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}
impl<D: DebugPls, const N: usize> DebugPls for [D; N] {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}
impl DebugPls for str {
fn fmt(&self, f: Formatter<'_>) {
f.write_expr(syn::ExprLit {
attrs: vec![],
lit: syn::LitStr::new(self, Span::call_site()).into(),
});
}
}
impl DebugPls for String {
fn fmt(&self, f: Formatter<'_>) {
DebugPls::fmt(self.as_str(), f);
}
}
impl<T: DebugPls, E: DebugPls> DebugPls for Result<T, E> {
fn fmt(&self, f: Formatter<'_>) {
match self {
Ok(t) => f.debug_tuple_struct("Ok").field(t).finish(),
Err(e) => f.debug_tuple_struct("Err").field(e).finish(),
}
}
}
impl<B: DebugPls, C: DebugPls> DebugPls for ControlFlow<B, C> {
fn fmt(&self, f: Formatter<'_>) {
match self {
ControlFlow::Break(b) => f.debug_tuple_struct("Break").field(b).finish(),
ControlFlow::Continue(c) => f.debug_tuple_struct("Continue").field(c).finish(),
}
}
}
impl<T: DebugPls> DebugPls for Option<T> {
fn fmt(&self, f: Formatter<'_>) {
match self {
Some(t) => f.debug_tuple_struct("Some").field(t).finish(),
None => f.debug_ident("None"),
}
}
}
impl<T: DebugPls> DebugPls for Poll<T> {
fn fmt(&self, f: Formatter<'_>) {
match self {
Poll::Ready(t) => f.debug_tuple_struct("Ready").field(t).finish(),
Poll::Pending => f.debug_ident("Pending"),
}
}
}

View file

@ -1,51 +0,0 @@
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
use crate::{DebugPls, Formatter};
impl<K: DebugPls, V: DebugPls, S: ::std::hash::BuildHasher> DebugPls for HashMap<K, V, S> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_map().entries(self).finish();
}
}
impl<K: DebugPls, V: DebugPls> DebugPls for BTreeMap<K, V> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_map().entries(self).finish();
}
}
impl<V: DebugPls, S: ::std::hash::BuildHasher> DebugPls for HashSet<V, S> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_set().entries(self).finish();
}
}
impl<V: DebugPls> DebugPls for BTreeSet<V> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_set().entries(self).finish();
}
}
impl<D: DebugPls> DebugPls for Vec<D> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}
impl<D: DebugPls> DebugPls for VecDeque<D> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}
impl<D: DebugPls> DebugPls for LinkedList<D> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}
impl<D: DebugPls> DebugPls for BinaryHeap<D> {
fn fmt(&self, f: Formatter<'_>) {
f.debug_list().entries(self).finish();
}
}

View file

@ -1,155 +0,0 @@
use syn::{
punctuated::{Pair, Punctuated},
token::{Bracket, Comma},
Attribute, Expr, ExprArray, ExprLit, Lit, LitInt, LitStr,
};
use crate::{DebugPls, Formatter};
impl DebugPls for Expr {
fn fmt(&self, f: Formatter<'_>) {
match self {
Expr::Array(val0) => f.debug_tuple_struct("Array").field(val0).finish(),
// Expr::Assign(val0) => f.debug_tuple_struct("Assign").field(val0).finish(),
// Expr::AssignOp(val0) => f.debug_tuple_struct("AssignOp").field(val0).finish(),
// Expr::Async(val0) => f.debug_tuple_struct("Async").field(val0).finish(),
// Expr::Await(val0) => f.debug_tuple_struct("Await").field(val0).finish(),
// Expr::Binary(val0) => f.debug_tuple_struct("Binary").field(val0).finish(),
// Expr::Block(val0) => f.debug_tuple_struct("Block").field(val0).finish(),
// Expr::Box(val0) => f.debug_tuple_struct("Box").field(val0).finish(),
// Expr::Break(val0) => f.debug_tuple_struct("Break").field(val0).finish(),
// Expr::Call(val0) => f.debug_tuple_struct("Call").field(val0).finish(),
// Expr::Cast(val0) => f.debug_tuple_struct("Cast").field(val0).finish(),
// Expr::Closure(val0) => f.debug_tuple_struct("Closure").field(val0).finish(),
// Expr::Continue(val0) => f.debug_tuple_struct("Continue").field(val0).finish(),
// Expr::Field(val0) => f.debug_tuple_struct("Field").field(val0).finish(),
// Expr::ForLoop(val0) => f.debug_tuple_struct("ForLoop").field(val0).finish(),
// Expr::Group(val0) => f.debug_tuple_struct("Group").field(val0).finish(),
// Expr::If(val0) => f.debug_tuple_struct("If").field(val0).finish(),
// Expr::Index(val0) => f.debug_tuple_struct("Index").field(val0).finish(),
// Expr::Let(val0) => f.debug_tuple_struct("Let").field(val0).finish(),
Expr::Lit(val0) => f.debug_tuple_struct("Lit").field(val0).finish(),
// Expr::Loop(val0) => f.debug_tuple_struct("Loop").field(val0).finish(),
// Expr::Macro(val0) => f.debug_tuple_struct("Macro").field(val0).finish(),
// Expr::Match(val0) => f.debug_tuple_struct("Match").field(val0).finish(),
// Expr::MethodCall(val0) => f.debug_tuple_struct("MethodCall").field(val0).finish(),
// Expr::Paren(val0) => f.debug_tuple_struct("Paren").field(val0).finish(),
// Expr::Path(val0) => f.debug_tuple_struct("Path").field(val0).finish(),
// Expr::Range(val0) => f.debug_tuple_struct("Range").field(val0).finish(),
// Expr::Reference(val0) => f.debug_tuple_struct("Reference").field(val0).finish(),
// Expr::Repeat(val0) => f.debug_tuple_struct("Repeat").field(val0).finish(),
// Expr::Return(val0) => f.debug_tuple_struct("Return").field(val0).finish(),
// Expr::Struct(val0) => f.debug_tuple_struct("Struct").field(val0).finish(),
// Expr::Try(val0) => f.debug_tuple_struct("Try").field(val0).finish(),
// Expr::TryBlock(val0) => f.debug_tuple_struct("TryBlock").field(val0).finish(),
// Expr::Tuple(val0) => f.debug_tuple_struct("Tuple").field(val0).finish(),
// Expr::Type(val0) => f.debug_tuple_struct("Type").field(val0).finish(),
// Expr::Unary(val0) => f.debug_tuple_struct("Unary").field(val0).finish(),
// Expr::Unsafe(val0) => f.debug_tuple_struct("Unsafe").field(val0).finish(),
// Expr::Verbatim(val0) => f.debug_tuple_struct("Verbatim").field(val0).finish(),
// Expr::While(val0) => f.debug_tuple_struct("While").field(val0).finish(),
// Expr::Yield(val0) => f.debug_tuple_struct("Yield").field(val0).finish(),
_ => todo!(),
}
}
}
impl DebugPls for ExprArray {
fn fmt(&self, f: Formatter<'_>) {
f.debug_struct("ExprArray")
.field("attrs", &self.attrs)
.field("bracket_token", &self.bracket_token)
.field("elems", &self.elems)
.finish();
}
}
impl DebugPls for ExprLit {
fn fmt(&self, f: Formatter<'_>) {
f.debug_struct("ExprLit")
.field("attrs", &self.attrs)
.field("lit", &self.lit)
.finish();
}
}
impl DebugPls for Lit {
fn fmt(&self, f: Formatter<'_>) {
match self {
Lit::Str(v0) => f.debug_tuple_struct("Str").field(v0).finish(),
// Lit::ByteStr(v0) => f.debug_tuple_struct("ByteStr").field(v0).finish(),
// Lit::Byte(v0) => f.debug_tuple_struct("Byte").field(v0).finish(),
// Lit::Char(v0) => f.debug_tuple_struct("Char").field(v0).finish(),
Lit::Int(v0) => f.debug_tuple_struct("Int").field(v0).finish(),
// Lit::Float(v0) => f.debug_tuple_struct("Float").field(v0).finish(),
// Lit::Bool(v0) => f.debug_tuple_struct("Bool").field(v0).finish(),
// Lit::Verbatim(v0) => f.debug_tuple_struct("Verbatim").field(v0).finish(),
_ => todo!(),
}
}
}
impl DebugPls for LitStr {
fn fmt(&self, f: Formatter<'_>) {
f.debug_struct("LitStr")
.field("value", &self.value())
.finish();
}
}
impl DebugPls for LitInt {
fn fmt(&self, f: Formatter<'_>) {
f.debug_struct("LitInt")
.field("value", &self.base10_digits())
.finish();
}
}
impl DebugPls for Attribute {
fn fmt(&self, f: Formatter<'_>) {
f.debug_struct("Attribute").finish_non_exhaustive();
}
}
impl<T: DebugPls, P: DebugPls> DebugPls for Punctuated<T, P> {
fn fmt(&self, f: Formatter<'_>) {
self.pairs()
.fold(f.debug_list(), |f, pair| match pair {
Pair::Punctuated(t, p) => f.entry(t).entry(p),
Pair::End(t) => f.entry(t),
})
.finish();
}
}
macro_rules! debug_units {
($($T:ident),*) => {$(
impl DebugPls for $T {
fn fmt(&self, f: Formatter<'_>) {
f.debug_ident(stringify!($T))
}
}
)*};
}
debug_units![Comma, Bracket];
#[cfg(test)]
mod tests {
use crate::color;
#[test]
fn pretty_colors() {
let code = r#"
[
"Hello, World! I am a long string",
420,
"Wait, you can't mix and match types in arrays, is this python?",
69,
"Nice."
]
"#;
let expr: syn::Expr = syn::parse_str(code).unwrap();
println!("{}", color(&expr));
}
}

View file

@ -1,79 +1,15 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(clippy::pedantic)]
#![forbid(unsafe_code)]
use syn::__private::{Span, TokenStream2};
mod impls;
mod debug_list;
mod debug_map;
mod debug_set;
mod debug_struct;
mod debug_tuple;
mod debug_tuple_struct;
pub use debug_list::DebugList;
pub use debug_map::DebugMap;
pub use debug_set::DebugSet;
pub use debug_struct::DebugStruct;
pub use debug_tuple::DebugTuple;
pub use debug_tuple_struct::DebugTupleStruct;
pub trait DebugPls {
fn fmt(&self, f: Formatter<'_>);
}
pub struct Formatter<'a> {
expr: &'a mut syn::Expr,
_expr: &'a (),
}
impl<'a> Formatter<'a> {
pub(crate) fn process(value: &dyn DebugPls) -> syn::Expr {
let mut expr = syn::Expr::Verbatim(TokenStream2::new());
value.fmt(Formatter { expr: &mut expr });
expr
}
}
pub fn write_expr(self, expr: impl Into<syn::Expr>) {
*self.expr = expr.into();
}
#[must_use]
pub fn debug_struct(self, name: &str) -> DebugStruct<'a> {
DebugStruct::new(self, name)
}
#[must_use]
pub fn debug_tuple(self) -> DebugTuple<'a> {
DebugTuple::new(self)
}
#[must_use]
pub fn debug_tuple_struct(self, name: &str) -> DebugTupleStruct<'a> {
DebugTupleStruct::new(self, name)
}
#[must_use]
pub fn debug_list(self) -> DebugList<'a> {
DebugList::new(self)
}
#[must_use]
pub fn debug_map(self) -> DebugMap<'a> {
DebugMap::new(self)
}
#[must_use]
pub fn debug_set(self) -> DebugSet<'a> {
DebugSet::new(self)
}
pub fn debug_ident(self, name: &str) {
let path: syn::Path = syn::Ident::new(name, Span::call_site()).into();
self.write_expr(syn::ExprPath {
attrs: vec![],
qself: None,
path,
});
impl<'a, D: DebugPls + ?Sized> DebugPls for &'a D {
fn fmt(&self, _: Formatter<'_>) {
}
}