Use ast attributes every where (remove HIR attributes).

This could be a [breaking-change] if your lint or syntax extension (is that even possible?) uses HIR attributes or literals.
This commit is contained in:
Nick Cameron
2015-09-14 21:58:20 +12:00
parent d2e13e822a
commit e9f1b06329
83 changed files with 1066 additions and 2557 deletions

View File

@@ -54,8 +54,8 @@ impl PpAnn for NoAnn {}
#[derive(Copy, Clone)]
pub struct CurrentCommentAndLiteral {
cur_cmnt: usize,
cur_lit: usize,
pub cur_cmnt: usize,
pub cur_lit: usize,
}
pub struct State<'a> {
@@ -450,26 +450,361 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
}
}
impl<'a> State<'a> {
pub fn ibox(&mut self, u: usize) -> io::Result<()> {
self.boxes.push(pp::Breaks::Inconsistent);
pp::ibox(&mut self.s, u)
pub trait PrintState<'a> {
fn writer(&mut self) -> &mut pp::Printer<'a>;
fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral;
fn literals(&self) -> &Option<Vec<comments::Literal>>;
fn word_space(&mut self, w: &str) -> io::Result<()> {
try!(word(self.writer(), w));
space(self.writer())
}
pub fn end(&mut self) -> io::Result<()> {
self.boxes.pop().unwrap();
pp::end(&mut self.s)
fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") }
fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") }
fn is_begin(&mut self) -> bool {
match self.writer().last_token() {
pp::Token::Begin(_) => true,
_ => false,
}
}
pub fn cbox(&mut self, u: usize) -> io::Result<()> {
self.boxes.push(pp::Breaks::Consistent);
pp::cbox(&mut self.s, u)
fn is_end(&mut self) -> bool {
match self.writer().last_token() {
pp::Token::End => true,
_ => false,
}
}
// is this the beginning of a line?
fn is_bol(&mut self) -> bool {
self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
}
fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
if !self.is_bol() {
try!(hardbreak(self.writer()))
}
Ok(())
}
// "raw box"
pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
self.boxes.push(b);
pp::rbox(&mut self.s, u, b)
fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
self.boxes().push(b);
pp::rbox(self.writer(), u, b)
}
fn ibox(&mut self, u: usize) -> io::Result<()> {
self.boxes().push(pp::Breaks::Inconsistent);
pp::ibox(self.writer(), u)
}
fn end(&mut self) -> io::Result<()> {
self.boxes().pop().unwrap();
pp::end(self.writer())
}
fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
where F: FnMut(&mut Self, &T) -> io::Result<()>,
{
try!(self.rbox(0, b));
let mut first = true;
for elt in elts {
if first { first = false; } else { try!(self.word_space(",")); }
try!(op(self, elt));
}
self.end()
}
fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
let mut cur_lit = self.cur_cmnt_and_lit().cur_lit;
let mut result = None;
if let &Some(ref lits) = self.literals()
{
while cur_lit < lits.len() {
let ltrl = (*lits)[cur_lit].clone();
if ltrl.pos > pos { break; }
cur_lit += 1;
if ltrl.pos == pos {
result = Some(ltrl);
break;
}
}
}
self.cur_cmnt_and_lit().cur_lit = cur_lit;
result
}
fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
loop {
match self.next_comment() {
Some(ref cmnt) => {
if (*cmnt).pos < pos {
try!(self.print_comment(cmnt));
self.cur_cmnt_and_lit().cur_cmnt += 1;
} else { break; }
}
_ => break
}
}
Ok(())
}
fn print_comment(&mut self,
cmnt: &comments::Comment) -> io::Result<()> {
match cmnt.style {
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1);
try!(zerobreak(self.writer()));
try!(word(self.writer(), &cmnt.lines[0]));
zerobreak(self.writer())
}
comments::Isolated => {
try!(self.hardbreak_if_not_bol());
for line in &cmnt.lines {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
try!(word(self.writer(), &line[..]));
}
try!(hardbreak(self.writer()));
}
Ok(())
}
comments::Trailing => {
try!(word(self.writer(), " "));
if cmnt.lines.len() == 1 {
try!(word(self.writer(), &cmnt.lines[0]));
hardbreak(self.writer())
} else {
try!(self.ibox(0));
for line in &cmnt.lines {
if !line.is_empty() {
try!(word(self.writer(), &line[..]));
}
try!(hardbreak(self.writer()));
}
self.end()
}
}
comments::BlankLine => {
// We need to do at least one, possibly two hardbreaks.
let is_semi = match self.writer().last_token() {
pp::Token::String(s, _) => ";" == s,
_ => false
};
if is_semi || self.is_begin() || self.is_end() {
try!(hardbreak(self.writer()));
}
hardbreak(self.writer())
}
}
}
fn next_comment(&mut self) -> Option<comments::Comment> {
let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt;
match *self.comments() {
Some(ref cmnts) => {
if cur_cmnt < cmnts.len() {
Some(cmnts[cur_cmnt].clone())
} else {
None
}
}
_ => None
}
}
fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
try!(self.maybe_print_comment(lit.span.lo));
match self.next_lit(lit.span.lo) {
Some(ref ltrl) => {
return word(self.writer(), &(*ltrl).lit);
}
_ => ()
}
match lit.node {
ast::LitStr(ref st, style) => self.print_string(&st, style),
ast::LitByte(byte) => {
let mut res = String::from("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
word(self.writer(), &res[..])
}
ast::LitChar(ch) => {
let mut res = String::from("'");
res.extend(ch.escape_default());
res.push('\'');
word(self.writer(), &res[..])
}
ast::LitInt(i, t) => {
match t {
ast::SignedIntLit(st, ast::Plus) => {
word(self.writer(),
&ast_util::int_ty_to_string(st, Some(i as i64)))
}
ast::SignedIntLit(st, ast::Minus) => {
let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
word(self.writer(),
&format!("-{}", istr))
}
ast::UnsignedIntLit(ut) => {
word(self.writer(), &ast_util::uint_ty_to_string(ut, Some(i)))
}
ast::UnsuffixedIntLit(ast::Plus) => {
word(self.writer(), &format!("{}", i))
}
ast::UnsuffixedIntLit(ast::Minus) => {
word(self.writer(), &format!("-{}", i))
}
}
}
ast::LitFloat(ref f, t) => {
word(self.writer(),
&format!(
"{}{}",
&f,
&ast_util::float_ty_to_string(t)))
}
ast::LitFloatUnsuffixed(ref f) => word(self.writer(), &f[..]),
ast::LitBool(val) => {
if val { word(self.writer(), "true") } else { word(self.writer(), "false") }
}
ast::LitByteStr(ref v) => {
let mut escaped: String = String::new();
for &ch in v.iter() {
escaped.extend(ascii::escape_default(ch)
.map(|c| c as char));
}
word(self.writer(), &format!("b\"{}\"", escaped))
}
}
}
fn print_string(&mut self, st: &str,
style: ast::StrStyle) -> io::Result<()> {
let st = match style {
ast::CookedStr => {
(format!("\"{}\"", st.escape_default()))
}
ast::RawStr(n) => {
(format!("r{delim}\"{string}\"{delim}",
delim=repeat("#", n),
string=st))
}
};
word(self.writer(), &st[..])
}
fn print_inner_attributes(&mut self,
attrs: &[ast::Attribute]) -> io::Result<()> {
let mut count = 0;
for attr in attrs {
match attr.node.style {
ast::AttrInner => {
try!(self.print_attribute(attr));
count += 1;
}
_ => {/* fallthrough */ }
}
}
if count > 0 {
try!(self.hardbreak_if_not_bol());
}
Ok(())
}
fn print_outer_attributes(&mut self,
attrs: &[ast::Attribute]) -> io::Result<()> {
let mut count = 0;
for attr in attrs {
match attr.node.style {
ast::AttrOuter => {
try!(self.print_attribute(attr));
count += 1;
}
_ => {/* fallthrough */ }
}
}
if count > 0 {
try!(self.hardbreak_if_not_bol());
}
Ok(())
}
fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(attr.span.lo));
if attr.node.is_sugared_doc {
word(self.writer(), &attr.value_str().unwrap())
} else {
match attr.node.style {
ast::AttrInner => try!(word(self.writer(), "#![")),
ast::AttrOuter => try!(word(self.writer(), "#[")),
}
try!(self.print_meta_item(&*attr.meta()));
word(self.writer(), "]")
}
}
fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
try!(self.ibox(indent_unit));
match item.node {
ast::MetaWord(ref name) => {
try!(word(self.writer(), &name));
}
ast::MetaNameValue(ref name, ref value) => {
try!(self.word_space(&name[..]));
try!(self.word_space("="));
try!(self.print_literal(value));
}
ast::MetaList(ref name, ref items) => {
try!(word(self.writer(), &name));
try!(self.popen());
try!(self.commasep(Consistent,
&items[..],
|s, i| s.print_meta_item(&**i)));
try!(self.pclose());
}
}
self.end()
}
}
impl<'a> PrintState<'a> for State<'a> {
fn writer(&mut self) -> &mut pp::Printer<'a> {
&mut self.s
}
fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
&mut self.boxes
}
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
&mut self.comments
}
fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral {
&mut self.cur_cmnt_and_lit
}
fn literals(&self) -> &Option<Vec<comments::Literal>> {
&self.literals
}
}
impl<'a> State<'a> {
pub fn cbox(&mut self, u: usize) -> io::Result<()> {
self.boxes.push(pp::Breaks::Consistent);
pp::cbox(&mut self.s, u)
}
pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
@@ -479,15 +814,6 @@ impl<'a> State<'a> {
self.nbsp()
}
pub fn word_space(&mut self, w: &str) -> io::Result<()> {
try!(word(&mut self.s, w));
space(&mut self.s)
}
pub fn popen(&mut self) -> io::Result<()> { word(&mut self.s, "(") }
pub fn pclose(&mut self) -> io::Result<()> { word(&mut self.s, ")") }
pub fn head(&mut self, w: &str) -> io::Result<()> {
// outer-box is consistent
try!(self.cbox(indent_unit));
@@ -523,25 +849,6 @@ impl<'a> State<'a> {
self.bclose_(span, indent_unit)
}
pub fn is_begin(&mut self) -> bool {
match self.s.last_token() {
pp::Token::Begin(_) => true,
_ => false,
}
}
pub fn is_end(&mut self) -> bool {
match self.s.last_token() {
pp::Token::End => true,
_ => false,
}
}
// is this the beginning of a line?
pub fn is_bol(&mut self) -> bool {
self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
}
pub fn in_cbox(&self) -> bool {
match self.boxes.last() {
Some(&last_box) => last_box == pp::Breaks::Consistent,
@@ -549,12 +856,6 @@ impl<'a> State<'a> {
}
}
pub fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
if !self.is_bol() {
try!(hardbreak(&mut self.s))
}
Ok(())
}
pub fn space_if_not_bol(&mut self) -> io::Result<()> {
if !self.is_bol() { try!(space(&mut self.s)); }
Ok(())
@@ -584,17 +885,6 @@ impl<'a> State<'a> {
word(&mut self.s, "*/")
}
pub fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> where
F: FnMut(&mut State, &T) -> io::Result<()>,
{
try!(self.rbox(0, b));
let mut first = true;
for elt in elts {
if first { first = false; } else { try!(self.word_space(",")); }
try!(op(self, elt));
}
self.end()
}
pub fn commasep_cmnt<T, F, G>(&mut self,
@@ -1326,58 +1616,6 @@ impl<'a> State<'a> {
self.ann.post(self, NodeSubItem(ii.id))
}
pub fn print_outer_attributes(&mut self,
attrs: &[ast::Attribute]) -> io::Result<()> {
let mut count = 0;
for attr in attrs {
match attr.node.style {
ast::AttrOuter => {
try!(self.print_attribute(attr));
count += 1;
}
_ => {/* fallthrough */ }
}
}
if count > 0 {
try!(self.hardbreak_if_not_bol());
}
Ok(())
}
pub fn print_inner_attributes(&mut self,
attrs: &[ast::Attribute]) -> io::Result<()> {
let mut count = 0;
for attr in attrs {
match attr.node.style {
ast::AttrInner => {
try!(self.print_attribute(attr));
count += 1;
}
_ => {/* fallthrough */ }
}
}
if count > 0 {
try!(self.hardbreak_if_not_bol());
}
Ok(())
}
pub fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(attr.span.lo));
if attr.node.is_sugared_doc {
word(&mut self.s, &attr.value_str().unwrap())
} else {
match attr.node.style {
ast::AttrInner => try!(word(&mut self.s, "#![")),
ast::AttrOuter => try!(word(&mut self.s, "#[")),
}
try!(self.print_meta_item(&*attr.meta()));
word(&mut self.s, "]")
}
}
pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
try!(self.maybe_print_comment(st.span.lo));
match st.node {
@@ -2620,29 +2858,6 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
try!(self.ibox(indent_unit));
match item.node {
ast::MetaWord(ref name) => {
try!(word(&mut self.s, &name));
}
ast::MetaNameValue(ref name, ref value) => {
try!(self.word_space(&name[..]));
try!(self.word_space("="));
try!(self.print_literal(value));
}
ast::MetaList(ref name, ref items) => {
try!(word(&mut self.s, &name));
try!(self.popen());
try!(self.commasep(Consistent,
&items[..],
|s, i| s.print_meta_item(&**i)));
try!(self.pclose());
}
}
self.end()
}
pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
match vp.node {
ast::ViewPathSimple(ident, ref path) => {
@@ -2832,181 +3047,6 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
try!(self.maybe_print_comment(lit.span.lo));
match self.next_lit(lit.span.lo) {
Some(ref ltrl) => {
return word(&mut self.s, &(*ltrl).lit);
}
_ => ()
}
match lit.node {
ast::LitStr(ref st, style) => self.print_string(&st, style),
ast::LitByte(byte) => {
let mut res = String::from("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
word(&mut self.s, &res[..])
}
ast::LitChar(ch) => {
let mut res = String::from("'");
res.extend(ch.escape_default());
res.push('\'');
word(&mut self.s, &res[..])
}
ast::LitInt(i, t) => {
match t {
ast::SignedIntLit(st, ast::Plus) => {
word(&mut self.s,
&ast_util::int_ty_to_string(st, Some(i as i64)))
}
ast::SignedIntLit(st, ast::Minus) => {
let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
word(&mut self.s,
&format!("-{}", istr))
}
ast::UnsignedIntLit(ut) => {
word(&mut self.s, &ast_util::uint_ty_to_string(ut, Some(i)))
}
ast::UnsuffixedIntLit(ast::Plus) => {
word(&mut self.s, &format!("{}", i))
}
ast::UnsuffixedIntLit(ast::Minus) => {
word(&mut self.s, &format!("-{}", i))
}
}
}
ast::LitFloat(ref f, t) => {
word(&mut self.s,
&format!(
"{}{}",
&f,
&ast_util::float_ty_to_string(t)))
}
ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]),
ast::LitBool(val) => {
if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
}
ast::LitByteStr(ref v) => {
let mut escaped: String = String::new();
for &ch in v.iter() {
escaped.extend(ascii::escape_default(ch)
.map(|c| c as char));
}
word(&mut self.s, &format!("b\"{}\"", escaped))
}
}
}
pub fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
match self.literals {
Some(ref lits) => {
while self.cur_cmnt_and_lit.cur_lit < lits.len() {
let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone();
if ltrl.pos > pos { return None; }
self.cur_cmnt_and_lit.cur_lit += 1;
if ltrl.pos == pos { return Some(ltrl); }
}
None
}
_ => None
}
}
pub fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
loop {
match self.next_comment() {
Some(ref cmnt) => {
if (*cmnt).pos < pos {
try!(self.print_comment(cmnt));
self.cur_cmnt_and_lit.cur_cmnt += 1;
} else { break; }
}
_ => break
}
}
Ok(())
}
pub fn print_comment(&mut self,
cmnt: &comments::Comment) -> io::Result<()> {
match cmnt.style {
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1);
try!(zerobreak(&mut self.s));
try!(word(&mut self.s, &cmnt.lines[0]));
zerobreak(&mut self.s)
}
comments::Isolated => {
try!(self.hardbreak_if_not_bol());
for line in &cmnt.lines {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
try!(word(&mut self.s, &line[..]));
}
try!(hardbreak(&mut self.s));
}
Ok(())
}
comments::Trailing => {
try!(word(&mut self.s, " "));
if cmnt.lines.len() == 1 {
try!(word(&mut self.s, &cmnt.lines[0]));
hardbreak(&mut self.s)
} else {
try!(self.ibox(0));
for line in &cmnt.lines {
if !line.is_empty() {
try!(word(&mut self.s, &line[..]));
}
try!(hardbreak(&mut self.s));
}
self.end()
}
}
comments::BlankLine => {
// We need to do at least one, possibly two hardbreaks.
let is_semi = match self.s.last_token() {
pp::Token::String(s, _) => ";" == s,
_ => false
};
if is_semi || self.is_begin() || self.is_end() {
try!(hardbreak(&mut self.s));
}
hardbreak(&mut self.s)
}
}
}
pub fn print_string(&mut self, st: &str,
style: ast::StrStyle) -> io::Result<()> {
let st = match style {
ast::CookedStr => {
(format!("\"{}\"", st.escape_default()))
}
ast::RawStr(n) => {
(format!("r{delim}\"{string}\"{delim}",
delim=repeat("#", n),
string=st))
}
};
word(&mut self.s, &st[..])
}
pub fn next_comment(&mut self) -> Option<comments::Comment> {
match self.comments {
Some(ref cmnts) => {
if self.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
Some(cmnts[self.cur_cmnt_and_lit.cur_cmnt].clone())
} else {
None
}
}
_ => None
}
}
pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
opt_abi: Option<abi::Abi>)
-> io::Result<()> {