about summary refs log tree commit diff
path: root/src/libsyntax_ext/format_foreign.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-07-24 16:01:38 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-07-24 16:01:38 -0700
commit4d8aa5989c3ecbcee9da63fdcf4564f71ac328fc (patch)
treee28251b7ff5a9e6e241448130b35381f47168f15 /src/libsyntax_ext/format_foreign.rs
parentf9e37625e6e9d90ee8b7200313de3915e2fc15a0 (diff)
downloadrust-4d8aa5989c3ecbcee9da63fdcf4564f71ac328fc.tar.gz
rust-4d8aa5989c3ecbcee9da63fdcf4564f71ac328fc.zip
Use suggestions for `printf` format
Diffstat (limited to 'src/libsyntax_ext/format_foreign.rs')
-rw-r--r--src/libsyntax_ext/format_foreign.rs54
1 files changed, 50 insertions, 4 deletions
diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs
index ff9663cdd3c..115f51c5e81 100644
--- a/src/libsyntax_ext/format_foreign.rs
+++ b/src/libsyntax_ext/format_foreign.rs
@@ -14,7 +14,7 @@ pub mod printf {
     /// Represents a single `printf`-style substitution.
     #[derive(Clone, PartialEq, Debug)]
     pub enum Substitution<'a> {
-        /// A formatted output substitution.
+        /// A formatted output substitution with its internal byte offset.
         Format(Format<'a>),
         /// A literal `%%` escape.
         Escape,
@@ -28,6 +28,23 @@ pub mod printf {
             }
         }
 
+        pub fn position(&self) -> Option<(usize, usize)> {
+            match *self {
+                Substitution::Format(ref fmt) => Some(fmt.position),
+                _ => None,
+            }
+        }
+
+        pub fn set_position(&mut self, start: usize, end: usize) {
+            match self {
+                Substitution::Format(ref mut fmt) => {
+                    fmt.position = (start, end);
+                }
+                _ => {}
+            }
+        }
+
+
         /// Translate this substitution into an equivalent Rust formatting directive.
         ///
         /// This ignores cases where the substitution does not have an exact equivalent, or where
@@ -57,6 +74,8 @@ pub mod printf {
         pub length: Option<&'a str>,
         /// Type of parameter being converted.
         pub type_: &'a str,
+        /// Byte offset for the start and end of this formatting directive.
+        pub position: (usize, usize),
     }
 
     impl<'a> Format<'a> {
@@ -257,19 +276,28 @@ pub mod printf {
     pub fn iter_subs(s: &str) -> Substitutions {
         Substitutions {
             s,
+            pos: 0,
         }
     }
 
     /// Iterator over substitutions in a string.
     pub struct Substitutions<'a> {
         s: &'a str,
+        pos: usize,
     }
 
     impl<'a> Iterator for Substitutions<'a> {
         type Item = Substitution<'a>;
         fn next(&mut self) -> Option<Self::Item> {
-            let (sub, tail) = parse_next_substitution(self.s)?;
+            let (mut sub, tail) = parse_next_substitution(self.s)?;
             self.s = tail;
+            match sub {
+                Substitution::Format(_) => if let Some((start, end)) = sub.position() {
+                    sub.set_position(start + self.pos, end + self.pos);
+                    self.pos += end;
+                }
+                Substitution::Escape => self.pos += 2,
+            }
             Some(sub)
         }
 
@@ -301,7 +329,9 @@ pub mod printf {
                 _ => {/* fall-through */},
             }
 
-            Cur::new_at_start(&s[start..])
+            //let _ = Cur::new_at_start_with_pos(&s[..], start);
+            //Cur::new_at_start(&s[start..])
+            Cur::new_at_start_with_pos(&s[..], start)
         };
 
         // This is meant to be a translation of the following regex:
@@ -355,6 +385,7 @@ pub mod printf {
                     precision: None,
                     length: None,
                     type_: at.slice_between(next).unwrap(),
+                    position: (start.at, next.at),
                 }),
                 next.slice_after()
             ));
@@ -541,6 +572,7 @@ pub mod printf {
         drop(next);
 
         end = at;
+        let position = (start.at, end.at);
 
         let f = Format {
             span: start.slice_between(end).unwrap(),
@@ -550,6 +582,7 @@ pub mod printf {
             precision,
             length,
             type_,
+            position,
         };
         Some((Substitution::Format(f), end.slice_after()))
     }
@@ -755,6 +788,12 @@ pub mod shell {
             }
         }
 
+        pub fn position(&self) -> Option<(usize, usize)> {
+            match *self {
+                _ => None,
+            }
+        }
+
         pub fn translate(&self) -> Option<String> {
             match *self {
                 Substitution::Ordinal(n) => Some(format!("{{{}}}", n)),
@@ -918,7 +957,7 @@ mod strcursor {
 
     pub struct StrCursor<'a> {
         s: &'a str,
-        at: usize,
+        pub at: usize,
     }
 
     impl<'a> StrCursor<'a> {
@@ -929,6 +968,13 @@ mod strcursor {
             }
         }
 
+        pub fn new_at_start_with_pos(s: &'a str, at: usize) -> StrCursor<'a> {
+            StrCursor {
+                s,
+                at,
+            }
+        }
+
         pub fn at_next_cp(mut self) -> Option<StrCursor<'a>> {
             match self.try_seek_right_cp() {
                 true => Some(self),