]> git.lizzy.rs Git - rust.git/blobdiff - src/libfmt_macros/lib.rs
Introduce InnerSpan abstraction
[rust.git] / src / libfmt_macros / lib.rs
index aacd6cec565a5a971576f7ae79cf00e273387f67..66355801b6c54d7acd6f3248379e3aeedf111b94 100644 (file)
@@ -9,6 +9,7 @@
        test(attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![deny(internal)]
 
 #![feature(nll)]
 #![feature(rustc_private)]
 use std::string;
 use std::iter;
 
+use syntax_pos::{InnerSpan, Symbol};
+
+#[derive(Copy, Clone)]
+struct InnerOffset(usize);
+
+impl InnerOffset {
+    fn to(self, end: InnerOffset) -> InnerSpan {
+        InnerSpan::new(self.0, end.0)
+    }
+}
+
 /// A piece is a portion of the format string which represents the next part
 /// to emit. These are emitted as a stream by the `Parser` class.
 #[derive(Copy, Clone, PartialEq)]
@@ -38,7 +50,7 @@ pub enum Piece<'a> {
 #[derive(Copy, Clone, PartialEq)]
 pub struct Argument<'a> {
     /// Where to find this argument
-    pub position: Position<'a>,
+    pub position: Position,
     /// How to format the argument
     pub format: FormatSpec<'a>,
 }
@@ -53,9 +65,9 @@ pub struct FormatSpec<'a> {
     /// Packed version of various flags provided
     pub flags: u32,
     /// The integer precision to use
-    pub precision: Count<'a>,
+    pub precision: Count,
     /// The string width requested for the resulting format
-    pub width: Count<'a>,
+    pub width: Count,
     /// The descriptor string representing the name of the format desired for
     /// this argument, this can be empty or any number of characters, although
     /// it is required to be one word.
@@ -64,16 +76,16 @@ pub struct FormatSpec<'a> {
 
 /// Enum describing where an argument for a format can be located.
 #[derive(Copy, Clone, PartialEq)]
-pub enum Position<'a> {
+pub enum Position {
     /// The argument is implied to be located at an index
     ArgumentImplicitlyIs(usize),
     /// The argument is located at a specific index given in the format
     ArgumentIs(usize),
     /// The argument has a name.
-    ArgumentNamed(&'a str),
+    ArgumentNamed(Symbol),
 }
 
-impl Position<'_> {
+impl Position {
     pub fn index(&self) -> Option<usize> {
         match self {
             ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
@@ -118,11 +130,11 @@ pub enum Flag {
 /// A count is used for the precision and width parameters of an integer, and
 /// can reference either an argument or a literal integer.
 #[derive(Copy, Clone, PartialEq)]
-pub enum Count<'a> {
+pub enum Count {
     /// The count is specified explicitly.
     CountIs(usize),
     /// The count is specified by the argument with the given name.
-    CountIsName(&'a str),
+    CountIsName(Symbol),
     /// The count is specified by the argument at the given index.
     CountIsParam(usize),
     /// The count is implied and cannot be explicitly specified.
@@ -133,9 +145,8 @@ pub struct ParseError {
     pub description: string::String,
     pub note: Option<string::String>,
     pub label: string::String,
-    pub start: SpanIndex,
-    pub end: SpanIndex,
-    pub secondary_label: Option<(string::String, SpanIndex, SpanIndex)>,
+    pub span: InnerSpan,
+    pub secondary_label: Option<(string::String, InnerSpan)>,
 }
 
 /// The parser structure for interpreting the input format string. This is
@@ -154,24 +165,15 @@ pub struct Parser<'a> {
     /// `Some(raw count)` when the string is "raw", used to position spans correctly
     style: Option<usize>,
     /// Start and end byte offset of every successfully parsed argument
-    pub arg_places: Vec<(SpanIndex, SpanIndex)>,
+    pub arg_places: Vec<InnerSpan>,
     /// Characters that need to be shifted
     skips: Vec<usize>,
-    /// Span offset of the last opening brace seen, used for error reporting
-    last_opening_brace_pos: Option<SpanIndex>,
+    /// Span of the last opening brace seen, used for error reporting
+    last_opening_brace: Option<InnerSpan>,
     /// Wether the source string is comes from `println!` as opposed to `format!` or `print!`
     append_newline: bool,
 }
 
-#[derive(Clone, Copy, Debug)]
-pub struct SpanIndex(pub usize);
-
-impl SpanIndex {
-    pub fn unwrap(self) -> usize {
-        self.0
-    }
-}
-
 impl<'a> Iterator for Parser<'a> {
     type Item = Piece<'a>;
 
@@ -179,19 +181,20 @@ fn next(&mut self) -> Option<Piece<'a>> {
         if let Some(&(pos, c)) = self.cur.peek() {
             match c {
                 '{' => {
-                    let curr_last_brace = self.last_opening_brace_pos;
-                    self.last_opening_brace_pos = Some(self.to_span_index(pos));
+                    let curr_last_brace = self.last_opening_brace;
+                    let byte_pos = self.to_span_index(pos);
+                    self.last_opening_brace = Some(byte_pos.to(byte_pos));
                     self.cur.next();
                     if self.consume('{') {
-                        self.last_opening_brace_pos = curr_last_brace;
+                        self.last_opening_brace = curr_last_brace;
 
                         Some(String(self.string(pos + 1)))
                     } else {
                         let arg = self.argument();
-                        if let Some(arg_pos) = self.must_consume('}').map(|end| {
-                            (self.to_span_index(pos), self.to_span_index(end + 1))
-                        }) {
-                            self.arg_places.push(arg_pos);
+                        if let Some(end) = self.must_consume('}') {
+                            let start = self.to_span_index(pos);
+                            let end = self.to_span_index(end + 1);
+                            self.arg_places.push(start.to(end));
                         }
                         Some(NextArgument(arg))
                     }
@@ -206,8 +209,7 @@ fn next(&mut self) -> Option<Piece<'a>> {
                             "unmatched `}` found",
                             "unmatched `}`",
                             "if you intended to print `}`, you can escape it using `}}`",
-                            err_pos,
-                            err_pos,
+                            err_pos.to(err_pos),
                         );
                         None
                     }
@@ -239,7 +241,7 @@ pub fn new(
             style,
             arg_places: vec![],
             skips,
-            last_opening_brace_pos: None,
+            last_opening_brace: None,
             append_newline,
         }
     }
@@ -251,15 +253,13 @@ fn err<S1: Into<string::String>, S2: Into<string::String>>(
         &mut self,
         description: S1,
         label: S2,
-        start: SpanIndex,
-        end: SpanIndex,
+        span: InnerSpan,
     ) {
         self.errors.push(ParseError {
             description: description.into(),
             note: None,
             label: label.into(),
-            start,
-            end,
+            span,
             secondary_label: None,
         });
     }
@@ -272,15 +272,13 @@ fn err_with_note<S1: Into<string::String>, S2: Into<string::String>, S3: Into<st
         description: S1,
         label: S2,
         note: S3,
-        start: SpanIndex,
-        end: SpanIndex,
+        span: InnerSpan,
     ) {
         self.errors.push(ParseError {
             description: description.into(),
             note: Some(note.into()),
             label: label.into(),
-            start,
-            end,
+            span,
             secondary_label: None,
         });
     }
@@ -301,22 +299,19 @@ fn consume(&mut self, c: char) -> bool {
         }
     }
 
-    fn raw(&self) -> usize {
-        self.style.map(|raw| raw + 1).unwrap_or(0)
-    }
-
-    fn to_span_index(&self, pos: usize) -> SpanIndex {
+    fn to_span_index(&self, pos: usize) -> InnerOffset {
         let mut pos = pos;
+        let raw = self.style.map(|raw| raw + 1).unwrap_or(0);
         for skip in &self.skips {
             if pos > *skip {
                 pos += 1;
-            } else if pos == *skip && self.raw() == 0 {
+            } else if pos == *skip && raw == 0 {
                 pos += 1;
             } else {
                 break;
             }
         }
-        SpanIndex(self.raw() + pos + 1)
+        InnerOffset(raw + pos + 1)
     }
 
     /// Forces consumption of the specified character. If the character is not
@@ -334,8 +329,8 @@ fn must_consume(&mut self, c: char) -> Option<usize> {
                 let label = "expected `}`".to_owned();
                 let (note, secondary_label) = if c == '}' {
                     (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
-                     self.last_opening_brace_pos.map(|pos| {
-                        ("because of this opening brace".to_owned(), pos, pos)
+                     self.last_opening_brace.map(|sp| {
+                        ("because of this opening brace".to_owned(), sp)
                      }))
                 } else {
                     (None, None)
@@ -344,8 +339,7 @@ fn must_consume(&mut self, c: char) -> Option<usize> {
                     description,
                     note,
                     label,
-                    start: pos,
-                    end: pos,
+                    span: pos.to(pos),
                     secondary_label,
                 });
                 None
@@ -359,8 +353,8 @@ fn must_consume(&mut self, c: char) -> Option<usize> {
                 let label = format!("expected `{:?}`", c);
                 let (note, secondary_label) = if c == '}' {
                     (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
-                     self.last_opening_brace_pos.map(|pos| {
-                        ("because of this opening brace".to_owned(), pos, pos)
+                     self.last_opening_brace.map(|sp| {
+                        ("because of this opening brace".to_owned(), sp)
                      }))
                 } else {
                     (None, None)
@@ -369,12 +363,11 @@ fn must_consume(&mut self, c: char) -> Option<usize> {
                     description,
                     note,
                     label,
-                    start: pos,
-                    end: pos,
+                    span: pos.to(pos),
                     secondary_label,
                 });
             } else {
-                self.err(description, format!("expected `{:?}`", c), pos, pos);
+                self.err(description, format!("expected `{:?}`", c), pos.to(pos));
             }
             None
         }
@@ -433,20 +426,24 @@ fn argument(&mut self) -> Argument<'a> {
     /// integer index of an argument, a named argument, or a blank string.
     /// Returns `Some(parsed_position)` if the position is not implicitly
     /// consuming a macro argument, `None` if it's the case.
-    fn position(&mut self) -> Option<Position<'a>> {
+    fn position(&mut self) -> Option<Position> {
         if let Some(i) = self.integer() {
             Some(ArgumentIs(i))
         } else {
             match self.cur.peek() {
-                Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())),
+                Some(&(_, c)) if c.is_alphabetic() => {
+                    Some(ArgumentNamed(Symbol::intern(self.word())))
+                }
                 Some(&(pos, c)) if c == '_' => {
                     let invalid_name = self.string(pos);
                     self.err_with_note(format!("invalid argument name `{}`", invalid_name),
                                        "invalid argument name",
                                        "argument names cannot start with an underscore",
-                                       self.to_span_index(pos),
-                                       self.to_span_index(pos + invalid_name.len()));
-                    Some(ArgumentNamed(invalid_name))
+                                        self.to_span_index(pos).to(
+                                            self.to_span_index(pos + invalid_name.len())
+                                        ),
+                                        );
+                    Some(ArgumentNamed(Symbol::intern(invalid_name)))
                 },
 
                 // This is an `ArgumentNext`.
@@ -554,7 +551,7 @@ fn format(&mut self) -> FormatSpec<'a> {
     /// Parses a Count parameter at the current position. This does not check
     /// for 'CountIsNextParam' because that is only used in precision, not
     /// width.
-    fn count(&mut self) -> Count<'a> {
+    fn count(&mut self) -> Count {
         if let Some(i) = self.integer() {
             if self.consume('$') {
                 CountIsParam(i)
@@ -568,7 +565,7 @@ fn count(&mut self) -> Count<'a> {
                 self.cur = tmp;
                 CountImplied
             } else if self.consume('$') {
-                CountIsName(word)
+                CountIsName(Symbol::intern(word))
             } else {
                 self.cur = tmp;
                 CountImplied
@@ -758,6 +755,8 @@ fn format_align_fill() {
     }
     #[test]
     fn format_counts() {
+        use syntax_pos::{GLOBALS, Globals, edition};
+        GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
         same("{:10s}",
              &[NextArgument(Argument {
                    position: ArgumentImplicitlyIs(0),
@@ -813,11 +812,12 @@ fn format_counts() {
                        fill: None,
                        align: AlignUnknown,
                        flags: 0,
-                       precision: CountIsName("b"),
-                       width: CountIsName("a"),
+                       precision: CountIsName(Symbol::intern("b")),
+                       width: CountIsName(Symbol::intern("a")),
                        ty: "s",
                    },
                })]);
+        });
     }
     #[test]
     fn format_flags() {