mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00

Some checks are pending
Rust / codestyle (push) Waiting to run
Rust / lint (push) Waiting to run
Rust / benchmark-lint (push) Waiting to run
Rust / compile (push) Waiting to run
Rust / docs (push) Waiting to run
Rust / compile-no-std (push) Waiting to run
Rust / test (beta) (push) Waiting to run
Rust / test (nightly) (push) Waiting to run
Rust / test (stable) (push) Waiting to run
135 lines
4.1 KiB
Rust
135 lines
4.1 KiB
Rust
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
//! Utilities for formatting SQL AST nodes with pretty printing support.
|
|
//!
|
|
//! The module provides formatters that implement the `Display` trait with support
|
|
//! for both regular (`{}`) and pretty (`{:#}`) formatting modes. Pretty printing
|
|
//! adds proper indentation and line breaks to make SQL statements more readable.
|
|
|
|
use core::fmt::{self, Display, Write};
|
|
|
|
/// A wrapper around a value that adds an indent to the value when displayed with {:#}.
|
|
pub(crate) struct Indent<T>(pub T);
|
|
|
|
const INDENT: &str = " ";
|
|
|
|
impl<T> Display for Indent<T>
|
|
where
|
|
T: Display,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
if f.alternate() {
|
|
f.write_str(INDENT)?;
|
|
write!(Indent(f), "{:#}", self.0)
|
|
} else {
|
|
self.0.fmt(f)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Adds an indent to the inner writer
|
|
impl<T> Write for Indent<T>
|
|
where
|
|
T: Write,
|
|
{
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
self.0.write_str(s)?;
|
|
// Our NewLine and SpaceOrNewline utils always print individual newlines as a single-character string.
|
|
if s == "\n" {
|
|
self.0.write_str(INDENT)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// A value that inserts a newline when displayed with {:#}, but not when displayed with {}.
|
|
pub(crate) struct NewLine;
|
|
|
|
impl Display for NewLine {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
if f.alternate() {
|
|
f.write_char('\n')
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A value that inserts a space when displayed with {}, but a newline when displayed with {:#}.
|
|
pub(crate) struct SpaceOrNewline;
|
|
|
|
impl Display for SpaceOrNewline {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
if f.alternate() {
|
|
f.write_char('\n')
|
|
} else {
|
|
f.write_char(' ')
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A value that displays a comma-separated list of values.
|
|
/// When pretty-printed (using {:#}), it displays each value on a new line.
|
|
pub(crate) struct DisplayCommaSeparated<'a, T: fmt::Display>(pub(crate) &'a [T]);
|
|
|
|
impl<T: fmt::Display> fmt::Display for DisplayCommaSeparated<'_, T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let mut first = true;
|
|
for t in self.0 {
|
|
if !first {
|
|
f.write_char(',')?;
|
|
SpaceOrNewline.fmt(f)?;
|
|
}
|
|
first = false;
|
|
t.fmt(f)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Displays a whitespace, followed by a comma-separated list that is indented when pretty-printed.
|
|
pub(crate) fn indented_list<T: fmt::Display>(f: &mut fmt::Formatter, items: &[T]) -> fmt::Result {
|
|
SpaceOrNewline.fmt(f)?;
|
|
Indent(DisplayCommaSeparated(items)).fmt(f)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_indent() {
|
|
struct TwoLines;
|
|
|
|
impl Display for TwoLines {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.write_str("line 1")?;
|
|
SpaceOrNewline.fmt(f)?;
|
|
f.write_str("line 2")
|
|
}
|
|
}
|
|
|
|
let indent = Indent(TwoLines);
|
|
assert_eq!(
|
|
indent.to_string(),
|
|
TwoLines.to_string(),
|
|
"Only the alternate form should be indented"
|
|
);
|
|
assert_eq!(format!("{:#}", indent), " line 1\n line 2");
|
|
}
|
|
}
|