You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by lu...@apache.org on 2026/09/25 07:24:38 UTC

(datafusion-sqlparser-rs) branch upstream/unary-minus-display-linear updated: Move the first-char probe into display_utils as first_char

This is an automated email from the ASF dual-hosted git repository.

LucaCappelletti94 pushed a commit to branch upstream/unary-minus-display-linear
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/upstream/unary-minus-display-linear by this push:
     new 253a4a1db Move the first-char probe into display_utils as first_char
253a4a1db is described below

commit 253a4a1db925ccc630e046de909fcbdab2f503ae
Author: LucaCappelletti94 <ca...@gmail.com>
AuthorDate: Fri Sep 25 09:24:31 2026 +0200

    Move the first-char probe into display_utils as first_char
---
 src/ast/mod.rs       | 18 ++----------------
 src/display_utils.rs | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index d604c3d99..744feef77 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -49,7 +49,7 @@ use crate::{
     tokenizer::{Span, Token},
 };
 use crate::{
-    display_utils::{Indent, NewLine},
+    display_utils::{first_char, Indent, NewLine},
     keywords::Keyword,
 };
 
@@ -8114,22 +8114,8 @@ impl fmt::Display for FunctionArg {
 /// must not abut one, since `--` starts a line comment and operator-run
 /// dialects fuse `-@`, `-~`, `-#`, `-!!` and `-||/` into single tokens.
 fn starts_with_operator_char(expr: &Expr) -> bool {
-    use fmt::Write;
-    struct FirstChar(Option<char>);
-    impl fmt::Write for FirstChar {
-        fn write_str(&mut self, s: &str) -> fmt::Result {
-            self.0 = self.0.or_else(|| s.chars().next());
-            // Stops the render once the first char is known.
-            match self.0 {
-                Some(_) => Err(fmt::Error),
-                None => Ok(()),
-            }
-        }
-    }
-    let mut first = FirstChar(None);
-    let _ = write!(first, "{expr}");
     const OPERATOR_CHARS: &str = "+-*/<>=~!@%#^&|";
-    first.0.is_some_and(|c| OPERATOR_CHARS.contains(c))
+    first_char(expr).is_some_and(|c| OPERATOR_CHARS.contains(c))
 }
 
 /// `FunctionArgOperator::Space` has no token of its own, so the name and the
diff --git a/src/display_utils.rs b/src/display_utils.rs
index ba36fccdd..280b00296 100644
--- a/src/display_utils.rs
+++ b/src/display_utils.rs
@@ -108,6 +108,28 @@ pub(crate) fn indented_list<T: fmt::Display>(f: &mut fmt::Formatter, items: &[T]
     Indent(DisplayCommaSeparated(items)).fmt(f)
 }
 
+/// The first char `value` displays, rendering only up to it.
+///
+/// The sink fails once it holds a char. Stopping there relies on every
+/// `Display` impl propagating the formatter's errors.
+pub(crate) fn first_char(value: &impl Display) -> Option<char> {
+    struct FirstChar(Option<char>);
+
+    impl Write for FirstChar {
+        fn write_str(&mut self, s: &str) -> fmt::Result {
+            self.0 = self.0.or_else(|| s.chars().next());
+            match self.0 {
+                Some(_) => Err(fmt::Error),
+                None => Ok(()),
+            }
+        }
+    }
+
+    let mut first = FirstChar(None);
+    let _ = write!(first, "{value}");
+    first.0
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -132,4 +154,23 @@ mod tests {
         );
         assert_eq!(format!("{:#}", indent), "  line 1\n  line 2");
     }
+
+    #[test]
+    fn test_first_char_stops_at_first_char() {
+        struct EmptyThenChars(core::cell::Cell<bool>);
+
+        impl Display for EmptyThenChars {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                f.write_str("")?;
+                f.write_str("ab")?;
+                self.0.set(true);
+                Ok(())
+            }
+        }
+
+        let value = EmptyThenChars(Default::default());
+        assert_eq!(first_char(&value), Some('a'));
+        assert!(!value.0.get(), "rendered past the first char");
+        assert_eq!(first_char(&""), None);
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org