use std::borrow::Cow;
use std::cell::Cell;
use std::io::{self, Write, Read};
-use std::iter::Peekable;
use std::vec;
pub enum AnnNode<'a> {
pub s: pp::Printer<'a>,
cm: Option<&'a SourceMap>,
comments: Option<Vec<comments::Comment>>,
- literals: Peekable<vec::IntoIter<comments::Literal>>,
cur_cmnt: usize,
boxes: Vec<pp::Breaks>,
ann: &'a (dyn PpAnn + 'a),
fn cur_cmnt(&mut self) -> &mut usize {
&mut self.cur_cmnt
}
-
- fn cur_lit(&mut self) -> Option<&comments::Literal> {
- self.literals.peek()
- }
-
- fn bump_lit(&mut self) -> Option<comments::Literal> {
- self.literals.next()
- }
}
#[allow(non_upper_case_globals)]
/// Requires you to pass an input filename and reader so that
-/// it can scan the input text for comments and literals to
-/// copy forward.
+/// it can scan the input text for comments to copy forward.
pub fn print_crate<'a>(cm: &'a SourceMap,
sess: &ParseSess,
krate: &hir::Crate,
filename: FileName,
input: &mut dyn Read,
out: Box<dyn Write + 'a>,
- ann: &'a dyn PpAnn,
- is_expanded: bool)
+ ann: &'a dyn PpAnn)
-> io::Result<()> {
- let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
+ let mut s = State::new_from_input(cm, sess, filename, input, out, ann);
// When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary.
filename: FileName,
input: &mut dyn Read,
out: Box<dyn Write + 'a>,
- ann: &'a dyn PpAnn,
- is_expanded: bool)
+ ann: &'a dyn PpAnn)
-> State<'a> {
- let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input);
-
- State::new(cm,
- out,
- ann,
- Some(cmnts),
- // If the code is post expansion, don't use the table of
- // literals, since it doesn't correspond with the literals
- // in the AST anymore.
- if is_expanded {
- None
- } else {
- Some(lits)
- })
+ let comments = comments::gather_comments(sess, filename, input);
+ State::new(cm, out, ann, Some(comments))
}
pub fn new(cm: &'a SourceMap,
out: Box<dyn Write + 'a>,
ann: &'a dyn PpAnn,
- comments: Option<Vec<comments::Comment>>,
- literals: Option<Vec<comments::Literal>>)
+ comments: Option<Vec<comments::Comment>>)
-> State<'a> {
State {
s: pp::mk_printer(out, default_columns),
cm: Some(cm),
comments,
- literals: literals.unwrap_or_default().into_iter().peekable(),
cur_cmnt: 0,
boxes: Vec::new(),
ann,
s: pp::mk_printer(Box::new(&mut wr), default_columns),
cm: None,
comments: None,
- literals: vec![].into_iter().peekable(),
cur_cmnt: 0,
boxes: Vec::new(),
ann,
fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
self.maybe_print_comment(lit.span.lo())?;
- if let Some(ltrl) = self.next_lit(lit.span.lo()) {
- return self.writer().word(ltrl.lit.clone());
- }
match lit.node {
hir::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
hir::LitKind::Err(st) => {
src_name,
&mut rdr,
box out,
- annotation.pp_ann(),
- true)
+ annotation.pp_ann())
})
}
src_name,
&mut rdr,
box out,
- annotation.pp_ann(),
- true);
+ annotation.pp_ann());
for node_id in uii.all_matching_node_ids(hir_map) {
let node = hir_map.get(node_id);
pp_state.print_node(node)?;
mod test {
use super::Cfg;
- use syntax::symbol::Symbol;
- use syntax::ast::*;
- use syntax::source_map::dummy_spanned;
use syntax_pos::DUMMY_SP;
+ use syntax::ast::*;
+ use syntax::symbol::Symbol;
use syntax::with_globals;
fn word_cfg(s: &str) -> Cfg {
let mi = dummy_meta_item_word("all");
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
+ let node = LitKind::Str(Symbol::intern("done"), StrStyle::Cooked);
+ let (token, suffix) = node.lit_token();
let mi = MetaItem {
path: Path::from_ident(Ident::from_str("all")),
- node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str(
- Symbol::intern("done"),
- StrStyle::Cooked,
- ))),
+ node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }),
span: DUMMY_SP,
};
assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
#[test]
fn test_parse_err() {
with_globals(|| {
+ let node = LitKind::Bool(false);
+ let (token, suffix) = node.lit_token();
let mi = MetaItem {
path: Path::from_ident(Ident::from_str("foo")),
- node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))),
+ node: MetaItemKind::NameValue(Lit { node, token, suffix, span: DUMMY_SP }),
span: DUMMY_SP,
};
assert!(Cfg::parse(&mi).is_err());
Some(TokenTree::Token(_, token::Eq)) => {
tokens.next();
return if let Some(TokenTree::Token(span, token)) = tokens.next() {
- LitKind::from_token(token)
- .map(|(node, token, suffix)| MetaItemKind::NameValue(Lit { node, token, suffix, span }))
+ LitKind::from_token(token).map(|(node, token, suffix)| {
+ MetaItemKind::NameValue(Lit { node, token, suffix, span })
+ })
} else {
None
};
}
}
- pub(crate) fn lit_token(&self) -> (token::Lit, Option<Symbol>) {
+ pub fn lit_token(&self) -> (token::Lit, Option<Symbol>) {
use std::ascii;
match *self {
use crate::ast;
use crate::source_map::SourceMap;
use crate::parse::lexer::{is_block_doc_comment, is_pattern_whitespace};
-use crate::parse::lexer::{self, ParseSess, StringReader, TokenAndSpan};
-use crate::print::pprust;
+use crate::parse::lexer::{self, ParseSess, StringReader};
use syntax_pos::{BytePos, CharPos, Pos, FileName};
use log::debug;
debug!("<<< consume comment");
}
-#[derive(Clone)]
-pub struct Literal {
- pub lit: String,
- pub pos: BytePos,
-}
-
// it appears this function is called only from pprust... that's
// probably not a good thing.
-pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut dyn Read)
- -> (Vec<Comment>, Vec<Literal>)
+pub fn gather_comments(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) -> Vec<Comment>
{
let mut src = String::new();
srdr.read_to_string(&mut src).unwrap();
let mut rdr = lexer::StringReader::new_raw(sess, source_file, None);
let mut comments: Vec<Comment> = Vec::new();
- let mut literals: Vec<Literal> = Vec::new();
let mut code_to_the_left = false; // Only code
let mut anything_to_the_left = false; // Code or comments
}
}
- let bstart = rdr.pos;
rdr.next_token();
- // discard, and look ahead; we're working with internal state
- let TokenAndSpan { tok, sp } = rdr.peek();
- if tok.is_lit() {
- rdr.with_str_from(bstart, |s| {
- debug!("tok lit: {}", s);
- literals.push(Literal {
- lit: s.to_string(),
- pos: sp.lo(),
- });
- })
- } else {
- debug!("tok: {}", pprust::token_to_string(&tok));
- }
code_to_the_left = true;
anything_to_the_left = true;
}
- (comments, literals)
+ comments
}
#[cfg(test)]
Applicability::MachineApplicable,
);
err.emit();
- return Ok(match float_suffix {
- "f32" => (ast::LitKind::Float(val, ast::FloatTy::F32), token::Float(val), suffix),
- "f64" => (ast::LitKind::Float(val, ast::FloatTy::F64), token::Float(val), suffix),
- _ => (ast::LitKind::FloatUnsuffixed(val), token::Float(val), suffix),
- });
+ return Ok((match float_suffix {
+ "f32" => ast::LitKind::Float(val, ast::FloatTy::F32),
+ "f64" => ast::LitKind::Float(val, ast::FloatTy::F64),
+ _ => ast::LitKind::FloatUnsuffixed(val),
+ }, token::Float(val), suffix));
} else {
unreachable!();
};
use syntax_pos::{self, BytePos};
use syntax_pos::{DUMMY_SP, FileName};
-use std::ascii;
use std::borrow::Cow;
use std::io::{self, Write, Read};
-use std::iter::Peekable;
use std::vec;
pub enum AnnNode<'a> {
pub struct State<'a> {
pub s: pp::Printer<'a>,
cm: Option<&'a SourceMap>,
- comments: Option<Vec<comments::Comment> >,
- literals: Peekable<vec::IntoIter<comments::Literal>>,
+ comments: Option<Vec<comments::Comment>>,
cur_cmnt: usize,
boxes: Vec<pp::Breaks>,
ann: &'a (dyn PpAnn+'a),
s: pp::mk_printer(writer, DEFAULT_COLUMNS),
cm: None,
comments: None,
- literals: vec![].into_iter().peekable(),
cur_cmnt: 0,
boxes: Vec::new(),
ann,
pub const DEFAULT_COLUMNS: usize = 78;
/// Requires you to pass an input filename and reader so that
-/// it can scan the input text for comments and literals to
-/// copy forward.
+/// it can scan the input text for comments to copy forward.
pub fn print_crate<'a>(cm: &'a SourceMap,
sess: &ParseSess,
krate: &ast::Crate,
out: Box<dyn Write+'a>,
ann: &'a dyn PpAnn,
is_expanded: bool) -> State<'a> {
- let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input);
-
- State::new(
- cm,
- out,
- ann,
- Some(cmnts),
- // If the code is post expansion, don't use the table of
- // literals, since it doesn't correspond with the literals
- // in the AST anymore.
- if is_expanded { None } else { Some(lits) },
- is_expanded
- )
+ let comments = comments::gather_comments(sess, filename, input);
+ State::new(cm, out, ann, Some(comments), is_expanded)
}
pub fn new(cm: &'a SourceMap,
out: Box<dyn Write+'a>,
ann: &'a dyn PpAnn,
comments: Option<Vec<comments::Comment>>,
- literals: Option<Vec<comments::Literal>>,
is_expanded: bool) -> State<'a> {
State {
s: pp::mk_printer(out, DEFAULT_COLUMNS),
cm: Some(cm),
comments,
- literals: literals.unwrap_or_default().into_iter().peekable(),
cur_cmnt: 0,
boxes: Vec::new(),
ann,
- is_expanded: is_expanded
+ is_expanded,
}
}
}
}
}
+fn literal_to_string(lit: token::Lit, suffix: Option<ast::Name>) -> String {
+ let mut out = match lit {
+ token::Byte(b) => format!("b'{}'", b),
+ token::Char(c) => format!("'{}'", c),
+ token::Err(c) => format!("'{}'", c),
+ token::Bool(c) |
+ token::Float(c) |
+ token::Integer(c) => c.to_string(),
+ token::Str_(s) => format!("\"{}\"", s),
+ token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}",
+ delim="#".repeat(n as usize),
+ string=s),
+ token::ByteStr(v) => format!("b\"{}\"", v),
+ token::ByteStrRaw(s, n) => format!("br{delim}\"{string}\"{delim}",
+ delim="#".repeat(n as usize),
+ string=s),
+ };
+
+ if let Some(suffix) = suffix {
+ out.push_str(&suffix.as_str())
+ }
+
+ out
+}
+
pub fn token_to_string(tok: &Token) -> String {
match *tok {
token::Eq => "=".to_string(),
token::SingleQuote => "'".to_string(),
/* Literals */
- token::Literal(lit, suf) => {
- let mut out = match lit {
- token::Bool(_) => panic!("literal token contains `Lit::Bool`"),
- token::Byte(b) => format!("b'{}'", b),
- token::Char(c) => format!("'{}'", c),
- token::Err(c) => format!("'{}'", c),
- token::Float(c) |
- token::Integer(c) => c.to_string(),
- token::Str_(s) => format!("\"{}\"", s),
- token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}",
- delim="#".repeat(n as usize),
- string=s),
- token::ByteStr(v) => format!("b\"{}\"", v),
- token::ByteStrRaw(s, n) => format!("br{delim}\"{string}\"{delim}",
- delim="#".repeat(n as usize),
- string=s),
- };
-
- if let Some(s) = suf {
- out.push_str(&s.as_str())
- }
-
- out
- }
+ token::Literal(lit, suf) => literal_to_string(lit, suf),
/* Name components */
token::Ident(s, false) => s.to_string(),
fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
fn cur_cmnt(&mut self) -> &mut usize;
- fn cur_lit(&mut self) -> Option<&comments::Literal>;
- fn bump_lit(&mut self) -> Option<comments::Literal>;
fn word_space<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
self.writer().word(w)?;
self.end()
}
- fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
- while let Some(ltrl) = self.cur_lit().cloned() {
- if ltrl.pos > pos { break; }
-
- // we don't need the value here since we're forced to clone cur_lit
- // due to lack of NLL.
- self.bump_lit();
- if ltrl.pos == pos {
- return Some(ltrl);
- }
- }
-
- None
- }
-
fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
while let Some(ref cmnt) = self.next_comment() {
if cmnt.pos < pos {
fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
self.maybe_print_comment(lit.span.lo())?;
- if let Some(ltrl) = self.next_lit(lit.span.lo()) {
- return self.writer().word(ltrl.lit.clone());
- }
- match lit.node {
- ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
- ast::LitKind::Err(st) => {
- let st = st.as_str().escape_debug().to_string();
- let mut res = String::with_capacity(st.len() + 2);
- res.push('\'');
- res.push_str(&st);
- res.push('\'');
- self.writer().word(res)
- }
- ast::LitKind::Byte(byte) => {
- let mut res = String::from("b'");
- res.extend(ascii::escape_default(byte).map(|c| c as char));
- res.push('\'');
- self.writer().word(res)
- }
- ast::LitKind::Char(ch) => {
- let mut res = String::from("'");
- res.extend(ch.escape_default());
- res.push('\'');
- self.writer().word(res)
- }
- ast::LitKind::Int(i, t) => {
- match t {
- ast::LitIntType::Signed(st) => {
- self.writer().word(st.val_to_string(i as i128))
- }
- ast::LitIntType::Unsigned(ut) => {
- self.writer().word(ut.val_to_string(i))
- }
- ast::LitIntType::Unsuffixed => {
- self.writer().word(i.to_string())
- }
- }
- }
- ast::LitKind::Float(ref f, t) => {
- self.writer().word(format!("{}{}", &f, t.ty_to_string()))
- }
- ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().to_string()),
- ast::LitKind::Bool(val) => {
- if val { self.writer().word("true") } else { self.writer().word("false") }
- }
- ast::LitKind::ByteStr(ref v) => {
- let mut escaped: String = String::new();
- for &ch in v.iter() {
- escaped.extend(ascii::escape_default(ch)
- .map(|c| c as char));
- }
- self.writer().word(format!("b\"{}\"", escaped))
- }
- }
+ self.writer().word(literal_to_string(lit.token, lit.suffix))
}
fn print_string(&mut self, st: &str,
fn cur_cmnt(&mut self) -> &mut usize {
&mut self.cur_cmnt
}
-
- fn cur_lit(&mut self) -> Option<&comments::Literal> {
- self.literals.peek()
- }
-
- fn bump_lit(&mut self) -> Option<comments::Literal> {
- self.literals.next()
- }
}
impl<'a> State<'a> {