1
Fork 0

Rollup merge of #56336 - nnethercote:clean-up-pp, r=nikomatsakis

Clean up and streamline the pretty-printer

Some minor improvements.
This commit is contained in:
kennytm 2018-12-01 01:05:59 +08:00
commit bdb901c865
No known key found for this signature in database
GPG key ID: FEF6C8051D0E013C
7 changed files with 254 additions and 232 deletions

View file

@ -25,6 +25,7 @@ use hir;
use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
use hir::{GenericParam, GenericParamKind, GenericArg};
use std::borrow::Cow;
use std::cell::Cell;
use std::io::{self, Write, Read};
use std::iter::Peekable;
@ -209,7 +210,7 @@ pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
String::from_utf8(wr).unwrap()
}
pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String {
pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility, w: S) -> String {
to_string(NO_ANN, |s| {
s.print_visibility(vis)?;
s.s.word(w)
@ -226,12 +227,13 @@ impl<'a> State<'a> {
self.s.word(" ")
}
pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
self.s.word(w)?;
self.nbsp()
}
pub fn head(&mut self, w: &str) -> io::Result<()> {
pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
let w = w.into();
// outer-box is consistent
self.cbox(indent_unit)?;
// head-box is inconsistent
@ -303,7 +305,7 @@ impl<'a> State<'a> {
pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
self.s.word("/*")?;
self.s.space()?;
self.s.word(&text[..])?;
self.s.word(text)?;
self.s.space()?;
self.s.word("*/")
}
@ -468,7 +470,7 @@ impl<'a> State<'a> {
self.end() // end the outer fn box
}
hir::ForeignItemKind::Static(ref t, m) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
self.head(visibility_qualified(&item.vis, "static"))?;
if m {
self.word_space("mut")?;
}
@ -480,7 +482,7 @@ impl<'a> State<'a> {
self.end() // end the outer cbox
}
hir::ForeignItemKind::Type => {
self.head(&visibility_qualified(&item.vis, "type"))?;
self.head(visibility_qualified(&item.vis, "type"))?;
self.print_name(item.name)?;
self.s.word(";")?;
self.end()?; // end the head-ibox
@ -495,7 +497,7 @@ impl<'a> State<'a> {
default: Option<hir::BodyId>,
vis: &hir::Visibility)
-> io::Result<()> {
self.s.word(&visibility_qualified(vis, ""))?;
self.s.word(visibility_qualified(vis, ""))?;
self.word_space("const")?;
self.print_ident(ident)?;
self.word_space(":")?;
@ -534,7 +536,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::Item(item))?;
match item.node {
hir::ItemKind::ExternCrate(orig_name) => {
self.head(&visibility_qualified(&item.vis, "extern crate"))?;
self.head(visibility_qualified(&item.vis, "extern crate"))?;
if let Some(orig_name) = orig_name {
self.print_name(orig_name)?;
self.s.space()?;
@ -547,7 +549,7 @@ impl<'a> State<'a> {
self.end()?; // end outer head-block
}
hir::ItemKind::Use(ref path, kind) => {
self.head(&visibility_qualified(&item.vis, "use"))?;
self.head(visibility_qualified(&item.vis, "use"))?;
self.print_path(path, false)?;
match kind {
@ -566,7 +568,7 @@ impl<'a> State<'a> {
self.end()?; // end outer head-block
}
hir::ItemKind::Static(ref ty, m, expr) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
self.head(visibility_qualified(&item.vis, "static"))?;
if m == hir::MutMutable {
self.word_space("mut")?;
}
@ -582,7 +584,7 @@ impl<'a> State<'a> {
self.end()?; // end the outer cbox
}
hir::ItemKind::Const(ref ty, expr) => {
self.head(&visibility_qualified(&item.vis, "const"))?;
self.head(visibility_qualified(&item.vis, "const"))?;
self.print_name(item.name)?;
self.word_space(":")?;
self.print_type(&ty)?;
@ -609,7 +611,7 @@ impl<'a> State<'a> {
self.ann.nested(self, Nested::Body(body))?;
}
hir::ItemKind::Mod(ref _mod) => {
self.head(&visibility_qualified(&item.vis, "mod"))?;
self.head(visibility_qualified(&item.vis, "mod"))?;
self.print_name(item.name)?;
self.nbsp()?;
self.bopen()?;
@ -618,18 +620,18 @@ impl<'a> State<'a> {
}
hir::ItemKind::ForeignMod(ref nmod) => {
self.head("extern")?;
self.word_nbsp(&nmod.abi.to_string())?;
self.word_nbsp(nmod.abi.to_string())?;
self.bopen()?;
self.print_foreign_mod(nmod, &item.attrs)?;
self.bclose(item.span)?;
}
hir::ItemKind::GlobalAsm(ref ga) => {
self.head(&visibility_qualified(&item.vis, "global asm"))?;
self.s.word(&ga.asm.as_str())?;
self.head(visibility_qualified(&item.vis, "global asm"))?;
self.s.word(ga.asm.as_str().get())?;
self.end()?
}
hir::ItemKind::Ty(ref ty, ref generics) => {
self.head(&visibility_qualified(&item.vis, "type"))?;
self.head(visibility_qualified(&item.vis, "type"))?;
self.print_name(item.name)?;
self.print_generic_params(&generics.params)?;
self.end()?; // end the inner ibox
@ -642,7 +644,7 @@ impl<'a> State<'a> {
self.end()?; // end the outer ibox
}
hir::ItemKind::Existential(ref exist) => {
self.head(&visibility_qualified(&item.vis, "existential type"))?;
self.head(visibility_qualified(&item.vis, "existential type"))?;
self.print_name(item.name)?;
self.print_generic_params(&exist.generics.params)?;
self.end()?; // end the inner ibox
@ -668,11 +670,11 @@ impl<'a> State<'a> {
self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?;
}
hir::ItemKind::Struct(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "struct"))?;
self.head(visibility_qualified(&item.vis, "struct"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
hir::ItemKind::Union(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "union"))?;
self.head(visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
hir::ItemKind::Impl(unsafety,
@ -795,7 +797,7 @@ impl<'a> State<'a> {
span: syntax_pos::Span,
visibility: &hir::Visibility)
-> io::Result<()> {
self.head(&visibility_qualified(visibility, "enum"))?;
self.head(visibility_qualified(visibility, "enum"))?;
self.print_name(name)?;
self.print_generic_params(&generics.params)?;
self.print_where_clause(&generics.where_clause)?;
@ -1587,14 +1589,14 @@ impl<'a> State<'a> {
}
pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
self.s.word(&i.to_string())
self.s.word(i.to_string())
}
pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
if ident.is_raw_guess() {
self.s.word(&format!("r#{}", ident.name))?;
self.s.word(format!("r#{}", ident.name))?;
} else {
self.s.word(&ident.as_str())?;
self.s.word(ident.as_str().get())?;
}
self.ann.post(self, AnnNode::Name(&ident.name))
}
@ -2010,7 +2012,7 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
s.ibox(indent_unit)?;
if let Some(arg_name) = arg_names.get(i) {
s.s.word(&arg_name.as_str())?;
s.s.word(arg_name.as_str().get())?;
s.s.word(":")?;
s.s.space()?;
} else if let Some(body_id) = body_id {
@ -2073,7 +2075,8 @@ impl<'a> State<'a> {
}
}
pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> {
pub fn print_bounds(&mut self, prefix: &'static str, bounds: &[hir::GenericBound])
-> io::Result<()> {
if !bounds.is_empty() {
self.s.word(prefix)?;
let mut first = true;
@ -2322,7 +2325,7 @@ impl<'a> State<'a> {
Some(Abi::Rust) => Ok(()),
Some(abi) => {
self.word_nbsp("extern")?;
self.word_nbsp(&abi.to_string())
self.word_nbsp(abi.to_string())
}
None => Ok(()),
}
@ -2332,7 +2335,7 @@ impl<'a> State<'a> {
match opt_abi {
Some(abi) => {
self.word_nbsp("extern")?;
self.word_nbsp(&abi.to_string())
self.word_nbsp(abi.to_string())
}
None => Ok(()),
}
@ -2342,7 +2345,7 @@ impl<'a> State<'a> {
header: hir::FnHeader,
vis: &hir::Visibility)
-> io::Result<()> {
self.s.word(&visibility_qualified(vis, ""))?;
self.s.word(visibility_qualified(vis, ""))?;
match header.constness {
hir::Constness::NotConst => {}
@ -2358,7 +2361,7 @@ impl<'a> State<'a> {
if header.abi != Abi::Rust {
self.word_nbsp("extern")?;
self.word_nbsp(&header.abi.to_string())?;
self.word_nbsp(header.abi.to_string())?;
}
self.s.word("fn")

View file

@ -530,7 +530,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
s.s.space()?;
s.s.word("as")?;
s.s.space()?;
s.s.word(&self.tables.get().expr_ty(expr).to_string())?;
s.s.word(self.tables.get().expr_ty(expr).to_string())?;
s.pclose()
}
_ => Ok(()),

View file

@ -185,7 +185,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
Some(orig_name) => format!("use {} as {};", orig_name, item.name),
None => format!("use {};", item.name),
};
let replacement = visibility_qualified(&item.vis, &base_replacement);
let replacement = visibility_qualified(&item.vis, base_replacement);
tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
.span_suggestion_short_with_applicability(
extern_crate.span,

View file

@ -2791,7 +2791,7 @@ impl<'a> Parser<'a> {
s.print_usize(float.trunc() as usize)?;
s.pclose()?;
s.s.word(".")?;
s.s.word(fstr.splitn(2, ".").last().unwrap())
s.s.word(fstr.splitn(2, ".").last().unwrap().to_string())
});
err.span_suggestion_with_applicability(
lo.to(self.prev_span),

View file

@ -140,13 +140,14 @@
//! calculation, SCAN will write "infinity" to the size and let PRINT consume
//! it.
//!
//! In this implementation (following the paper, again) the SCAN process is
//! the method called `Printer::pretty_print`, and the 'PRINT' process is the method
//! called `Printer::print`.
//! In this implementation (following the paper, again) the SCAN process is the
//! methods called `Printer::pretty_print_*`, and the 'PRINT' process is the
//! method called `Printer::print`.
use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::borrow::Cow;
/// How to break. Described in more detail in the module docs.
#[derive(Clone, Copy, PartialEq)]
@ -169,7 +170,10 @@ pub struct BeginToken {
#[derive(Clone)]
pub enum Token {
String(String, isize),
// In practice a string token contains either a `&'static str` or a
// `String`. `Cow` is overkill for this because we never modify the data,
// but it's more convenient than rolling our own more specialized type.
String(Cow<'static, str>, isize),
Break(BreakToken),
Begin(BeginToken),
End,
@ -309,84 +313,86 @@ impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token {
self.buf[self.right].token.clone()
}
/// be very careful with this!
/// Be very careful with this!
pub fn replace_last_token(&mut self, t: Token) {
self.buf[self.right].token = t;
}
pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
debug!("pp Vec<{},{}>", self.left, self.right);
match token {
Token::Eof => {
if !self.scan_stack.is_empty() {
self.check_stack(0);
self.advance_left()?;
}
self.indent(0);
Ok(())
}
Token::Begin(b) => {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.left = 0;
self.right = 0;
} else {
self.advance_right();
}
debug!("pp Begin({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
let right = self.right;
self.scan_push(right);
Ok(())
}
Token::End => {
if self.scan_stack.is_empty() {
debug!("pp End/print Vec<{},{}>", self.left, self.right);
self.print(token, 0)
} else {
debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: token, size: -1 };
let right = self.right;
self.scan_push(right);
Ok(())
}
}
Token::Break(b) => {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.left = 0;
self.right = 0;
} else {
self.advance_right();
}
debug!("pp Break({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
fn pretty_print_eof(&mut self) -> io::Result<()> {
if !self.scan_stack.is_empty() {
self.check_stack(0);
self.advance_left()?;
}
self.indent(0);
Ok(())
}
fn pretty_print_begin(&mut self, b: BeginToken) -> io::Result<()> {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.left = 0;
self.right = 0;
} else {
self.advance_right();
}
debug!("pp Begin({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total };
let right = self.right;
self.scan_push(right);
Ok(())
}
fn pretty_print_end(&mut self) -> io::Result<()> {
if self.scan_stack.is_empty() {
debug!("pp End/print Vec<{},{}>", self.left, self.right);
self.print_end()
} else {
debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: Token::End, size: -1 };
let right = self.right;
self.scan_push(right);
self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
self.right_total += b.blank_space;
Ok(())
}
Token::String(s, len) => {
if self.scan_stack.is_empty() {
debug!("pp String('{}')/print Vec<{},{}>",
s, self.left, self.right);
self.print(Token::String(s, len), len)
} else {
debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
self.right_total += len;
self.check_stream()
}
}
}
}
fn pretty_print_break(&mut self, b: BreakToken) -> io::Result<()> {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.left = 0;
self.right = 0;
} else {
self.advance_right();
}
debug!("pp Break({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
self.check_stack(0);
let right = self.right;
self.scan_push(right);
self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total };
self.right_total += b.blank_space;
Ok(())
}
fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
if self.scan_stack.is_empty() {
debug!("pp String('{}')/print Vec<{},{}>",
s, self.left, self.right);
self.print_string(s, len)
} else {
debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
self.right_total += len;
self.check_stream()
}
}
pub fn check_stream(&mut self) -> io::Result<()> {
debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
self.left, self.right, self.left_total, self.right_total);
@ -405,19 +411,24 @@ impl<'a> Printer<'a> {
}
Ok(())
}
pub fn scan_push(&mut self, x: usize) {
debug!("scan_push {}", x);
self.scan_stack.push_front(x);
}
pub fn scan_pop(&mut self) -> usize {
self.scan_stack.pop_front().unwrap()
}
pub fn scan_top(&mut self) -> usize {
*self.scan_stack.front().unwrap()
}
pub fn scan_pop_bottom(&mut self) -> usize {
self.scan_stack.pop_back().unwrap()
}
pub fn advance_right(&mut self) {
self.right += 1;
self.right %= self.buf_max_len;
@ -427,6 +438,7 @@ impl<'a> Printer<'a> {
}
assert_ne!(self.right, self.left);
}
pub fn advance_left(&mut self) -> io::Result<()> {
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
self.left, self.buf[self.left].size);
@ -461,6 +473,7 @@ impl<'a> Printer<'a> {
Ok(())
}
pub fn check_stack(&mut self, k: isize) {
if !self.scan_stack.is_empty() {
let x = self.scan_top();
@ -488,6 +501,7 @@ impl<'a> Printer<'a> {
}
}
}
pub fn print_newline(&mut self, amount: isize) -> io::Result<()> {
debug!("NEWLINE {}", amount);
let ret = write!(self.out, "\n");
@ -495,10 +509,12 @@ impl<'a> Printer<'a> {
self.indent(amount);
ret
}
pub fn indent(&mut self, amount: isize) {
debug!("INDENT {}", amount);
self.pending_indentation += amount;
}
pub fn get_top(&mut self) -> PrintStackElem {
match self.print_stack.last() {
Some(el) => *el,
@ -508,62 +524,50 @@ impl<'a> Printer<'a> {
}
}
}
pub fn print_str(&mut self, s: &str) -> io::Result<()> {
while self.pending_indentation > 0 {
write!(self.out, " ")?;
self.pending_indentation -= 1;
pub fn print_begin(&mut self, b: BeginToken, l: isize) -> io::Result<()> {
if l > self.space {
let col = self.margin - self.space + b.offset;
debug!("print Begin -> push broken block at col {}", col);
self.print_stack.push(PrintStackElem {
offset: col,
pbreak: PrintStackBreak::Broken(b.breaks)
});
} else {
debug!("print Begin -> push fitting block");
self.print_stack.push(PrintStackElem {
offset: 0,
pbreak: PrintStackBreak::Fits
});
}
write!(self.out, "{}", s)
Ok(())
}
pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
debug!("print {} {} (remaining line space={})", token, l,
self.space);
debug!("{}", buf_str(&self.buf,
self.left,
self.right,
6));
match token {
Token::Begin(b) => {
if l > self.space {
let col = self.margin - self.space + b.offset;
debug!("print Begin -> push broken block at col {}", col);
self.print_stack.push(PrintStackElem {
offset: col,
pbreak: PrintStackBreak::Broken(b.breaks)
});
} else {
debug!("print Begin -> push fitting block");
self.print_stack.push(PrintStackElem {
offset: 0,
pbreak: PrintStackBreak::Fits
});
}
Ok(())
}
Token::End => {
debug!("print End -> pop End");
let print_stack = &mut self.print_stack;
assert!(!print_stack.is_empty());
print_stack.pop().unwrap();
Ok(())
}
Token::Break(b) => {
let top = self.get_top();
match top.pbreak {
PrintStackBreak::Fits => {
pub fn print_end(&mut self) -> io::Result<()> {
debug!("print End -> pop End");
let print_stack = &mut self.print_stack;
assert!(!print_stack.is_empty());
print_stack.pop().unwrap();
Ok(())
}
pub fn print_break(&mut self, b: BreakToken, l: isize) -> io::Result<()> {
let top = self.get_top();
match top.pbreak {
PrintStackBreak::Fits => {
debug!("print Break({}) in fitting block", b.blank_space);
self.space -= b.blank_space;
self.indent(b.blank_space);
Ok(())
}
PrintStackBreak::Broken(Breaks::Consistent) => {
}
PrintStackBreak::Broken(Breaks::Consistent) => {
debug!("print Break({}+{}) in consistent block",
top.offset, b.offset);
let ret = self.print_newline(top.offset + b.offset);
self.space = self.margin - (top.offset + b.offset);
ret
}
PrintStackBreak::Broken(Breaks::Inconsistent) => {
}
PrintStackBreak::Broken(Breaks::Inconsistent) => {
if l > self.space {
debug!("print Break({}+{}) w/ newline in inconsistent",
top.offset, b.offset);
@ -577,20 +581,37 @@ impl<'a> Printer<'a> {
self.space -= b.blank_space;
Ok(())
}
}
}
}
Token::String(ref s, len) => {
debug!("print String({})", s);
assert_eq!(l, len);
// assert!(l <= space);
self.space -= len;
self.print_str(s)
}
Token::Eof => {
// Eof should never get here.
panic!();
}
}
}
pub fn print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
debug!("print String({})", s);
// assert!(len <= space);
self.space -= len;
while self.pending_indentation > 0 {
write!(self.out, " ")?;
self.pending_indentation -= 1;
}
write!(self.out, "{}", s)
}
pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
debug!("print {} {} (remaining line space={})", token, l,
self.space);
debug!("{}", buf_str(&self.buf,
self.left,
self.right,
6));
match token {
Token::Begin(b) => self.print_begin(b, l),
Token::End => self.print_end(),
Token::Break(b) => self.print_break(b, l),
Token::String(s, len) => {
assert_eq!(len, l);
self.print_string(s, len)
}
Token::Eof => panic!(), // Eof should never get here.
}
}
@ -598,10 +619,10 @@ impl<'a> Printer<'a> {
/// "raw box"
pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> {
self.pretty_print(Token::Begin(BeginToken {
self.pretty_print_begin(BeginToken {
offset: indent as isize,
breaks: b
}))
})
}
/// Inconsistent breaking box
@ -615,30 +636,24 @@ impl<'a> Printer<'a> {
}
pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> {
self.pretty_print(Token::Break(BreakToken {
self.pretty_print_break(BreakToken {
offset: off,
blank_space: n as isize
}))
})
}
pub fn end(&mut self) -> io::Result<()> {
self.pretty_print(Token::End)
self.pretty_print_end()
}
pub fn eof(&mut self) -> io::Result<()> {
self.pretty_print(Token::Eof)
self.pretty_print_eof()
}
pub fn word(&mut self, wrd: &str) -> io::Result<()> {
self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize))
}
pub fn huge_word(&mut self, wrd: &str) -> io::Result<()> {
self.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY))
}
pub fn zero_word(&mut self, wrd: &str) -> io::Result<()> {
self.pretty_print(Token::String(wrd.to_string(), 0))
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) -> io::Result<()> {
let s = wrd.into();
let len = s.len() as isize;
self.pretty_print_string(s, len)
}
fn spaces(&mut self, n: usize) -> io::Result<()> {

View file

@ -29,6 +29,7 @@ use syntax_pos::{DUMMY_SP, FileName};
use tokenstream::{self, TokenStream, TokenTree};
use std::ascii;
use std::borrow::Cow;
use std::io::{self, Write, Read};
use std::iter::Peekable;
use std::vec;
@ -444,7 +445,7 @@ pub trait PrintState<'a> {
fn cur_lit(&mut self) -> Option<&comments::Literal>;
fn bump_lit(&mut self) -> Option<comments::Literal>;
fn word_space(&mut self, w: &str) -> io::Result<()> {
fn word_space<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
self.writer().word(w)?;
self.writer().space()
}
@ -539,7 +540,7 @@ pub trait PrintState<'a> {
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1);
self.writer().zerobreak()?;
self.writer().word(&cmnt.lines[0])?;
self.writer().word(cmnt.lines[0].clone())?;
self.writer().zerobreak()
}
comments::Isolated => {
@ -548,7 +549,7 @@ pub trait PrintState<'a> {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
self.writer().word(&line[..])?;
self.writer().word(line.clone())?;
}
self.writer().hardbreak()?;
}
@ -559,13 +560,13 @@ pub trait PrintState<'a> {
self.writer().word(" ")?;
}
if cmnt.lines.len() == 1 {
self.writer().word(&cmnt.lines[0])?;
self.writer().word(cmnt.lines[0].clone())?;
self.writer().hardbreak()
} else {
self.ibox(0)?;
for line in &cmnt.lines {
if !line.is_empty() {
self.writer().word(&line[..])?;
self.writer().word(line.clone())?;
}
self.writer().hardbreak()?;
}
@ -610,7 +611,7 @@ pub trait PrintState<'a> {
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);
return self.writer().word(ltrl.lit.clone());
}
match lit.node {
ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
@ -618,31 +619,31 @@ pub trait PrintState<'a> {
let mut res = String::from("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
self.writer().word(&res[..])
self.writer().word(res)
}
ast::LitKind::Char(ch) => {
let mut res = String::from("'");
res.extend(ch.escape_default());
res.push('\'');
self.writer().word(&res[..])
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))
self.writer().word(st.val_to_string(i as i128))
}
ast::LitIntType::Unsigned(ut) => {
self.writer().word(&ut.val_to_string(i))
self.writer().word(ut.val_to_string(i))
}
ast::LitIntType::Unsuffixed => {
self.writer().word(&i.to_string())
self.writer().word(i.to_string())
}
}
}
ast::LitKind::Float(ref f, t) => {
self.writer().word(&format!("{}{}", &f, t.ty_to_string()))
self.writer().word(format!("{}{}", &f, t.ty_to_string()))
}
ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()),
ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().get()),
ast::LitKind::Bool(val) => {
if val { self.writer().word("true") } else { self.writer().word("false") }
}
@ -652,7 +653,7 @@ pub trait PrintState<'a> {
escaped.extend(ascii::escape_default(ch)
.map(|c| c as char));
}
self.writer().word(&format!("b\"{}\"", escaped))
self.writer().word(format!("b\"{}\"", escaped))
}
}
}
@ -669,7 +670,7 @@ pub trait PrintState<'a> {
string=st))
}
};
self.writer().word(&st[..])
self.writer().word(st)
}
fn print_inner_attributes(&mut self,
@ -727,7 +728,7 @@ pub trait PrintState<'a> {
if segment.ident.name != keywords::CrateRoot.name() &&
segment.ident.name != keywords::DollarCrate.name()
{
self.writer().word(&segment.ident.as_str())?;
self.writer().word(segment.ident.as_str().get())?;
} else if segment.ident.name == keywords::DollarCrate.name() {
self.print_dollar_crate(segment.ident.span.ctxt())?;
}
@ -746,7 +747,7 @@ pub trait PrintState<'a> {
}
self.maybe_print_comment(attr.span.lo())?;
if attr.is_sugared_doc {
self.writer().word(&attr.value_str().unwrap().as_str())?;
self.writer().word(attr.value_str().unwrap().as_str().get())?;
self.writer().hardbreak()
} else {
match attr.style {
@ -807,7 +808,7 @@ pub trait PrintState<'a> {
fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> {
match tt {
TokenTree::Token(_, ref tk) => {
self.writer().word(&token_to_string(tk))?;
self.writer().word(token_to_string(tk))?;
match *tk {
parse::token::DocComment(..) => {
self.writer().hardbreak()
@ -816,11 +817,11 @@ pub trait PrintState<'a> {
}
}
TokenTree::Delimited(_, ref delimed) => {
self.writer().word(&token_to_string(&delimed.open_token()))?;
self.writer().word(token_to_string(&delimed.open_token()))?;
self.writer().space()?;
self.print_tts(delimed.stream())?;
self.writer().space()?;
self.writer().word(&token_to_string(&delimed.close_token()))
self.writer().word(token_to_string(&delimed.close_token()))
},
}
}
@ -889,12 +890,13 @@ impl<'a> State<'a> {
self.s.cbox(u)
}
pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
self.s.word(w)?;
self.nbsp()
}
pub fn head(&mut self, w: &str) -> io::Result<()> {
pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
let w = w.into();
// outer-box is consistent
self.cbox(INDENT_UNIT)?;
// head-box is inconsistent
@ -956,7 +958,7 @@ impl<'a> State<'a> {
pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
self.s.word("/*")?;
self.s.space()?;
self.s.word(&text[..])?;
self.s.word(text)?;
self.s.space()?;
self.s.word("*/")
}
@ -1129,7 +1131,7 @@ impl<'a> State<'a> {
self.end() // end the outer fn box
}
ast::ForeignItemKind::Static(ref t, m) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
self.head(visibility_qualified(&item.vis, "static"))?;
if m {
self.word_space("mut")?;
}
@ -1141,7 +1143,7 @@ impl<'a> State<'a> {
self.end() // end the outer cbox
}
ast::ForeignItemKind::Ty => {
self.head(&visibility_qualified(&item.vis, "type"))?;
self.head(visibility_qualified(&item.vis, "type"))?;
self.print_ident(item.ident)?;
self.s.word(";")?;
self.end()?; // end the head-ibox
@ -1164,7 +1166,7 @@ impl<'a> State<'a> {
vis: &ast::Visibility)
-> io::Result<()>
{
self.s.word(&visibility_qualified(vis, ""))?;
self.s.word(visibility_qualified(vis, ""))?;
self.word_space("const")?;
self.print_ident(ident)?;
self.word_space(":")?;
@ -1203,7 +1205,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::Item(item))?;
match item.node {
ast::ItemKind::ExternCrate(orig_name) => {
self.head(&visibility_qualified(&item.vis, "extern crate"))?;
self.head(visibility_qualified(&item.vis, "extern crate"))?;
if let Some(orig_name) = orig_name {
self.print_name(orig_name)?;
self.s.space()?;
@ -1216,14 +1218,14 @@ impl<'a> State<'a> {
self.end()?; // end outer head-block
}
ast::ItemKind::Use(ref tree) => {
self.head(&visibility_qualified(&item.vis, "use"))?;
self.head(visibility_qualified(&item.vis, "use"))?;
self.print_use_tree(tree)?;
self.s.word(";")?;
self.end()?; // end inner head-block
self.end()?; // end outer head-block
}
ast::ItemKind::Static(ref ty, m, ref expr) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
self.head(visibility_qualified(&item.vis, "static"))?;
if m == ast::Mutability::Mutable {
self.word_space("mut")?;
}
@ -1239,7 +1241,7 @@ impl<'a> State<'a> {
self.end()?; // end the outer cbox
}
ast::ItemKind::Const(ref ty, ref expr) => {
self.head(&visibility_qualified(&item.vis, "const"))?;
self.head(visibility_qualified(&item.vis, "const"))?;
self.print_ident(item.ident)?;
self.word_space(":")?;
self.print_type(ty)?;
@ -1264,7 +1266,7 @@ impl<'a> State<'a> {
self.print_block_with_attrs(body, &item.attrs)?;
}
ast::ItemKind::Mod(ref _mod) => {
self.head(&visibility_qualified(&item.vis, "mod"))?;
self.head(visibility_qualified(&item.vis, "mod"))?;
self.print_ident(item.ident)?;
if _mod.inline || self.is_expanded {
@ -1281,18 +1283,18 @@ impl<'a> State<'a> {
}
ast::ItemKind::ForeignMod(ref nmod) => {
self.head("extern")?;
self.word_nbsp(&nmod.abi.to_string())?;
self.word_nbsp(nmod.abi.to_string())?;
self.bopen()?;
self.print_foreign_mod(nmod, &item.attrs)?;
self.bclose(item.span)?;
}
ast::ItemKind::GlobalAsm(ref ga) => {
self.head(&visibility_qualified(&item.vis, "global_asm!"))?;
self.s.word(&ga.asm.as_str())?;
self.head(visibility_qualified(&item.vis, "global_asm!"))?;
self.s.word(ga.asm.as_str().get())?;
self.end()?;
}
ast::ItemKind::Ty(ref ty, ref generics) => {
self.head(&visibility_qualified(&item.vis, "type"))?;
self.head(visibility_qualified(&item.vis, "type"))?;
self.print_ident(item.ident)?;
self.print_generic_params(&generics.params)?;
self.end()?; // end the inner ibox
@ -1305,7 +1307,7 @@ impl<'a> State<'a> {
self.end()?; // end the outer ibox
}
ast::ItemKind::Existential(ref bounds, ref generics) => {
self.head(&visibility_qualified(&item.vis, "existential type"))?;
self.head(visibility_qualified(&item.vis, "existential type"))?;
self.print_ident(item.ident)?;
self.print_generic_params(&generics.params)?;
self.end()?; // end the inner ibox
@ -1326,11 +1328,11 @@ impl<'a> State<'a> {
)?;
}
ast::ItemKind::Struct(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "struct"))?;
self.head(visibility_qualified(&item.vis, "struct"))?;
self.print_struct(struct_def, generics, item.ident, item.span, true)?;
}
ast::ItemKind::Union(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "union"))?;
self.head(visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.ident, item.span, true)?;
}
ast::ItemKind::Impl(unsafety,
@ -1479,7 +1481,7 @@ impl<'a> State<'a> {
generics: &ast::Generics, ident: ast::Ident,
span: syntax_pos::Span,
visibility: &ast::Visibility) -> io::Result<()> {
self.head(&visibility_qualified(visibility, "enum"))?;
self.head(visibility_qualified(visibility, "enum"))?;
self.print_ident(ident)?;
self.print_generic_params(&generics.params)?;
self.print_where_clause(&generics.where_clause)?;
@ -1514,9 +1516,9 @@ impl<'a> State<'a> {
ast::VisibilityKind::Restricted { ref path, .. } => {
let path = to_string(|s| s.print_path(path, false, 0));
if path == "self" || path == "super" {
self.word_nbsp(&format!("pub({})", path))
self.word_nbsp(format!("pub({})", path))
} else {
self.word_nbsp(&format!("pub(in {})", path))
self.word_nbsp(format!("pub(in {})", path))
}
}
ast::VisibilityKind::Inherited => Ok(())
@ -2415,19 +2417,19 @@ impl<'a> State<'a> {
pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
if ident.is_raw_guess() {
self.s.word(&format!("r#{}", ident))?;
self.s.word(format!("r#{}", ident))?;
} else {
self.s.word(&ident.as_str())?;
self.s.word(ident.as_str().get())?;
}
self.ann.post(self, AnnNode::Ident(&ident))
}
pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
self.s.word(&i.to_string())
self.s.word(i.to_string())
}
pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
self.s.word(&name.as_str())?;
self.s.word(name.as_str().get())?;
self.ann.post(self, AnnNode::Name(&name))
}
@ -2851,10 +2853,8 @@ impl<'a> State<'a> {
}
}
pub fn print_type_bounds(&mut self,
prefix: &str,
bounds: &[ast::GenericBound])
-> io::Result<()> {
pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound])
-> io::Result<()> {
if !bounds.is_empty() {
self.s.word(prefix)?;
let mut first = true;
@ -3146,7 +3146,7 @@ impl<'a> State<'a> {
Some(Abi::Rust) => Ok(()),
Some(abi) => {
self.word_nbsp("extern")?;
self.word_nbsp(&abi.to_string())
self.word_nbsp(abi.to_string())
}
None => Ok(())
}
@ -3157,7 +3157,7 @@ impl<'a> State<'a> {
match opt_abi {
Some(abi) => {
self.word_nbsp("extern")?;
self.word_nbsp(&abi.to_string())
self.word_nbsp(abi.to_string())
}
None => Ok(())
}
@ -3166,7 +3166,7 @@ impl<'a> State<'a> {
pub fn print_fn_header_info(&mut self,
header: ast::FnHeader,
vis: &ast::Visibility) -> io::Result<()> {
self.s.word(&visibility_qualified(vis, ""))?;
self.s.word(visibility_qualified(vis, ""))?;
match header.constness.node {
ast::Constness::NotConst => {}
@ -3178,7 +3178,7 @@ impl<'a> State<'a> {
if header.abi != Abi::Rust {
self.word_nbsp("extern")?;
self.word_nbsp(&header.abi.to_string())?;
self.word_nbsp(header.abi.to_string())?;
}
self.s.word("fn")

View file

@ -492,6 +492,10 @@ impl LocalInternedString {
symbol: Symbol::intern(self.string)
}
}
pub fn get(&self) -> &'static str {
self.string
}
}
impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString